title: Surpassing same-origin policy with server side requests - NodeJS/Express
body: <p>I'm trying to achieve a structure described in <a href="https://www.sitepoint.com/working-around-origin-policy/" rel="nofollow noreferrer">this article - "Using a Web Proxy"</a> using a NodeJS server with Express. I need to access the html of an embedded iframe which is of course impossible due to same-origin policy. As a workaround, I figured that I could simply request the iframe on my server and then pass it on to the client. </p>
  
  <p>I made an entry point on my server called <code>/getIframe</code>.</p>
  
  <p>When the client requests <code>/getIframe</code>, my server makes a <a href="https://www.npmjs.com/package/request" rel="nofollow noreferrer">request</a> to the desired location and saves the page as a html document (using <a href="https://nodejs.org/api/fs.html" rel="nofollow noreferrer">fs</a>) which is then sent back to the client. This works fine but all scripts/css included in the html are not being passed as <a href="https://www.npmjs.com/package/request" rel="nofollow noreferrer">request</a> only gets the html. </p>
  
  <p>So, I downloaded the scripts/css manually and voilà, it's working. Here is the code.</p>
  
  <pre><code>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);
    });
  })
  </code></pre>
  
  <p>Invoked like this</p>
  
  <pre><code>&lt;iframe src={"/getIframe"}&gt;&lt;/iframe&gt;
  </code></pre>
  
  <p>I now have the behaviour I was looking for but the need of manually downloading the script is not ideal. </p>
  
  <p>Is there a way to request a page on a Node server and just pass it on to the client with all the content (scripts, css etc.)? </p>
  
  <p>What I'm looking for is something like</p>
  
  <pre><code>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(..)
    });
  })
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I've tried the answer provided by @Dafuck and although it is a better way of redirecting to a desired address, the resource issue still remains.</p>
  
  <p>@Dafuck suggested the following solution</p>
  
  <pre><code>app.use('/getIframe', function(req, res, next) {
      request.get({ url: "http://www.iframeurl.com/something" }).pipe(res);
  })
  </code></pre>
  
  <p>Which also can be achieved with </p>
  
  <pre><code>app.use('/getIframe', function(req, res, next) {
      req.pipe(request("http://www.iframeurl.com/something")).pipe(res);
  })
  </code></pre>
  
  <p>Both solutions redirect to the desired address from which the html is forwarded. And that's nice. The problem is that all scripts/links included in <code>&lt;head&gt;</code> of the retrieved html are then pointing to the server address like <code>http://localhost:3000</code> where they obviously don't exist. </p>
  
  <p>Example: The html of <code>http://www.example.com</code> looks like this</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  
  &lt;head&gt;
    &lt;meta http-equiv=content-type content="text/html; charset=utf-8" lang=en&gt;
    &lt;meta name=viewport content="width=device-width" /&gt;
    &lt;link href="somecss.css" rel="stylesheet"&gt;
    &lt;script type="text/javascript" src="somejs.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  
  &lt;body&gt;
    Example
  &lt;/body&gt;
  
  &lt;/html&gt;
  </code></pre>
  
  <p>Using either of the two methods mentioned above, requesting <code>/getIframe</code> from my server will return the correct html of <code>http://www.example.com</code> <strong>but</strong> the browser will try to fetch <code>somejs.js</code>and <code>somecss.css</code> from <code>http://localhost:3000</code> and as mentioned before, fail as all resources are found on <code>http://www.emample.com</code>.</p>
  
  <p>I've tried yet another approach using <a href="https://github.com/nodejitsu/node-http-proxy" rel="nofollow noreferrer">http-proxy</a>.</p>
  
  <pre><code>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"});
  });
  </code></pre>
  
  <p>Sadly, it seems like the last solution is a dead end as I get a strange response from the source I'm trying to fetch. My guess is that the source is preventing addition of x-forward headers.</p>