HTTP-запрос Ajax через страницу HTTPS
У меня есть сайт с некоторыми страницами по соединению HTTPS. На этих страницах HTTPS я должен использовать HTTP-запрос Ajax для поиска некоторых ошибок, таких как пустые поля. Но это сообщения об ошибках не приходят. Есть ли какое-либо решение, или я должен сделать этот запрос AJAX для файла по соединению HTTPS?
8 ответов
Это невозможно из-за одинаковой политики происхождения.
Вам также нужно будет переключить запросы Ajax на https.
Без какого-либо решения на стороне сервера, Theres - это только один способ, которым защищенная страница может получить что-то от небезопасной страницы / запроса, и это считается postMessage и всплывающее окно
Я сказал, что всплывающее окно не позволяет смешивать контент. Но всплывающее окно на самом деле не смешивается. У него есть собственное окно, но он все еще может общаться с открывателем с помощью postMessage.
Таким образом, вы можете открыть новую страницу http с window.open(...)
и это делает запрос для вас (то есть, если сайт также использует CORS)
XDomain пришёл в голову, когда я написал это, но здесь есть современный подход, использующий новый API fetch, преимущество заключается в потоковой передаче больших файлов, недостатком является то, что он не будет работать во всех браузерах.
Вы помещаете этот прокси-скрипт на любую страницу http
onmessage = evt => {
const port = evt.ports[0]
fetch(...evt.data).then(res => {
// the response is not clonable
// so we make a new plain object
const obj = {
bodyUsed: false,
headers: [...res.headers],
ok: res.ok,
redirected: res.redurected,
status: res.status,
statusText: res.statusText,
type: res.type,
url: res.url
}
port.postMessage(obj)
// Pipe the request to the port (MessageChannel)
const reader = res.body.getReader()
const pump = () => reader.read()
.then(({value, done}) => done
? port.postMessage(done)
: (port.postMessage(value), pump())
)
// start the pipe
pump()
})
}
Затем вы открываете всплывающее окно на своей странице https (обратите внимание, что вы можете сделать это только в случае взаимодействия с пользователем, иначе оно будет заблокировано).
window.popup = window.open(http://.../proxy.html)
создайте свою служебную функцию
function xfetch(...args) {
// tell the proxy to make the request
const ms = new MessageChannel
popup.postMessage(args, '*', [ms.port1])
// Resolves when the headers comes
return new Promise((rs, rj) => {
// First message will resolve the Response Object
ms.port2.onmessage = ({data}) => {
const stream = new ReadableStream({
start(controller) {
// Change the onmessage to pipe the remaning request
ms.port2.onmessage = evt => {
if (evt.data === true) // Done?
controller.close()
else // enqueue the buffer to the stream
controller.enqueue(evt.data)
}
}
})
// Construct a new response with the
// response headers and a stream
rs(new Response(stream, data))
}
})
}
И сделайте запрос, как вы обычно делаете с API выборки
xfetch('http://httpbin.org/get')
.then(res => res.text())
.then(console.log)
Тем не менее, это можно сделать с помощью следующих шагов:
отправить запрос https ajax на ваш сайт (тот же домен)
jQuery.ajax({ 'url' : '//same_domain.com/ajax_receiver.php', 'type' : 'get', 'data' : {'foo' : 'bar'}, 'success' : function(response) { console.log('Successful request'); } }).fail(function(xhr, err) { console.error('Request error'); });
получить ajax-запрос, например, по php, и сделать CURL-запрос на получение любого желаемого веб-сайта по http.
use linslin\yii2\curl; $curl = new curl\Curl(); $curl->get('http://example.com');
В некоторых случаях односторонний запрос без ответа может быть отправлен на сервер TCP без сертификата SSL. TCP-сервер, в отличие от HTTP-сервера, перехватит ваш запрос. Однако не будет никакого доступа к любым данным, отправленным из браузера, потому что браузер не будет отправлять данные без проверки положительного сертификата. А в особых случаях даже голого TCP-сигнала без каких-либо данных достаточно для выполнения некоторых задач. Например, для устройства IoT в локальной сети, чтобы начать подключение к внешней службе. Ссылка на сайт
Это своего рода триггер Wake Up, который работает на порте без какой-либо защиты.
В случае, если требуется ответ, это может быть реализовано с использованием защищенного публичного https-сервера, который может отправлять необходимые данные обратно в браузер, используя, например, веб-сокеты.
Сделайте обходной API в server.js. У меня это работает.
app.post('/by-pass-api',function(req, response){
const url = req.body.url;
console.log("calling url", url);
request.get(
url,
(error, res, body) => {
if (error) {
console.error(error)
return response.status(200).json({'content': "error"})
}
return response.status(200).json(JSON.parse(body))
},
)
})
И назовите это с помощью axios или fetch следующим образом:
const options = {
method: 'POST',
headers: {'content-type': 'application/json'},
url:`http://localhost:3000/by-pass-api`, // your environment
data: { url }, // your https request here
};
Я создал модуль под названием cors-bypass
, что позволяет вам делать это без необходимости сервера. Оно использует postMessage
отправлять междоменные события, которые используются для предоставления фиктивных HTTP API (fetch
, WebSocket
, XMLHTTPRequest
так далее.).
Он в основном делает то же самое, что и ответ Endless, но не требует изменений кода для его использования.
Пример использования:
import { Client, WebSocket } from 'cors-bypass'
const client = new Client()
await client.openServerInNewTab({
serverUrl: 'http://random-domain.com/server.html',
adapterUrl: 'https://your-site.com/adapter.html'
})
const ws = new WebSocket('ws://echo.websocket.org')
ws.onopen = () => ws.send('hello')
ws.onmessage = ({ data }) => console.log('received', data)
Это работает для меня. Сделайте обходной API в server.js или index.js. Я использую библиотеку express.js.
import express from 'express';
import bodyParser from 'body-parser'; // custom_code
import axios from 'axios'; // custom-code
let app = express();
const jsonParser = bodyParser.json();
app.post('/by-pass-api', jsonParser, async (req, response) => {
const { url } = req.body;
const data = { data: req.body.data };
const result = await axios.post(url, data);
response.send({ success: true, result: result });
});
app.listen(3000, () => {
console.log(`Server is running as on port 3000`);
});
Создайте функцию для вызова вашего локального сервера (вашего сервера приложений) с помощью axios или выборки следующим образом:
URL:
http://your-http-api-url
: это внешний http-адрес.
axios.post("http://localhost:3000/by-pass-api", {
headers: { "content-type": "application/json" },
url: `http://your-http-api-url`,
data: {...your_payload},
})
Из javascript я пробовал несколькими способами и не смог.
Вам нужно решение на стороне сервера, например, на C# Я создал контроллер, который вызывает http, en десериализует объект, и в результате я при вызове из javascript выполняю запрос из моего https: // домен в мой htpps:// домен. Пожалуйста, смотрите мой код C#:
[Authorize]
public class CurrencyServicesController : Controller
{
HttpClient client;
//GET: CurrencyServices/Consultar?url=valores?moedas=USD&alt=json
public async Task<dynamic> Consultar(string url)
{
client = new HttpClient();
client.BaseAddress = new Uri("http://api.promasters.net.br/cotacao/v1/");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
System.Net.Http.HttpResponseMessage response = client.GetAsync(url).Result;
var FromURL = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject(FromURL);
}
И позвольте мне показать вам мою клиентскую часть (Javascript)
<script async>
$(document).ready(function (data) {
var TheUrl = '@Url.Action("Consultar", "CurrencyServices")?url=valores';
$.getJSON(TheUrl)
.done(function (data) {
$('#DolarQuotation').html(
'$ ' + data.valores.USD.valor.toFixed(2) + ','
);
$('#EuroQuotation').html(
'€ ' + data.valores.EUR.valor.toFixed(2) + ','
);
$('#ARGPesoQuotation').html(
'Ar$ ' + data.valores.ARS.valor.toFixed(2) + ''
);
});
});
Я желаю, чтобы это помогло вам! Привет