Превосходя политику одного источника с запросами на стороне сервера - NodeJS/Express
Я пытаюсь создать структуру, описанную в этой статье - "Использование веб-прокси", используя сервер NodeJS с Express. Мне нужен доступ к html встроенного iframe, что, конечно, невозможно из-за политики того же происхождения. В качестве обходного пути я решил, что могу просто запросить iframe на своем сервере и затем передать его клиенту.
Я сделал точку входа на моем сервере под названием /getIframe
,
Когда клиент запрашивает /getIframe
Мой сервер делает запрос в нужное место и сохраняет страницу в виде html-документа (используя fs), который затем отправляется обратно клиенту. Это работает нормально, но все скрипты / CSS, включенные в HTML, не передаются, так как запрос получает только HTML.
Итак, я скачал скрипты / CSS вручную и вуаля, это работает. Вот код
app.get('/getIframe', function(req, res, next) {
request("http://www.iframeurl.com/something", function(error, response, body) {
fs.writeFileSync('iframe.html', body, 'utf8');
var html = fs.readFileSync('iframe.html', 'utf8')
res.send(html);
});
})
Вызывается так
<iframe src={"/getIframe"}></iframe>
Теперь у меня есть поведение, которое я искал, но необходимость ручной загрузки сценария не идеальна.
Есть ли способ запросить страницу на сервере Node и просто передать ее клиенту со всем содержимым (скриптами, CSS и т. Д.)?
Я ищу что-то вроде
app.get('/getIframe', function(req, res, next) {
request("http://www.iframeurl.com/something", function(error, response, body) {
//pass on the requested page in a response with res.send(thePage) or render it with res.render(..)
});
})
ОБНОВИТЬ
Я попробовал ответ, предоставленный @Dafuck, и, хотя это лучший способ перенаправления на нужный адрес, проблема с ресурсом все еще остается.
@Dafuck предложил следующее решение
app.use('/getIframe', function(req, res, next) {
request.get({ url: "http://www.iframeurl.com/something" }).pipe(res);
})
Что также может быть достигнуто с
app.use('/getIframe', function(req, res, next) {
req.pipe(request("http://www.iframeurl.com/something")).pipe(res);
})
Оба решения перенаправляют на нужный адрес, с которого пересылается HTML. И это мило. Проблема в том, что все скрипты / ссылки включены в <head>
из полученного html затем указывают на адрес сервера, как http://localhost:3000
где они явно не существуют.
Пример: HTML-код http://www.example.com
выглядит так
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=content-type content="text/html; charset=utf-8" lang=en>
<meta name=viewport content="width=device-width" />
<link href="somecss.css" rel="stylesheet">
<script type="text/javascript" src="somejs.js"></script>
</head>
<body>
Example
</body>
</html>
Используя любой из двух методов, упомянутых выше, запрашивая /getIframe
с моего сервера вернет правильный HTML http://www.example.com
но браузер попытается получить somejs.js
а также somecss.css
от http://localhost:3000
и, как упоминалось ранее, потерпеть неудачу, так как все ресурсы http://www.emample.com
,
Я попробовал еще один подход с использованием http-прокси.
const httpProxy = require('http-proxy');
const apiProxy = httpProxy.createProxyServer(
{
prependPath: false,
ignorePath: true,
changeOrigin: true,
xfwd: true,
}
);
app.all("/getIframe", function(req, res) {
apiProxy.web(req, res, {target: "http://www.example.com"});
});
К сожалению, кажется, что последнее решение - тупик, поскольку я получаю странный ответ от источника, который пытаюсь найти. Я предполагаю, что источник препятствует добавлению заголовков x-forward.
1 ответ
Просто передайте результат запроса res, чтобы вернуть страницу в ответ
request.post({ url: 'http://www.example.com', form: { foo: 'bar' }}).pipe(res);
Что в основном похоже на это:
request.get({url: "http://yolo"},function(err, response, body){
if(err) return res.end();
res.write(body);
res.setStatus(response.statusCode);
res.setHeader("Content-type", response.headers['content-type']);
return res.end();
});