Превосходя политику одного источника с запросами на стороне сервера - 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();
});
Другие вопросы по тегам