[SOLVED] Fetching external resource inside React component on Node.js

Issue

This Content is from Stack Overflow. Question asked by stckvrw

Suppose the following simple example.

We have Node app.js rendering a React component on the server-side:

let http = require('http');
let React = require('react');
let ReactDOMServer = require('react-dom/server');
let Component = require('./Component.js');

http.createServer((req, res) => {
    res.writeHead(200);
    let markup = ReactDOMServer.renderToStaticMarkup(Component());
    res.end(markup);
}).listen(3000);

And our Component.js looks like:

let React = require('react');

function Component() {
    return React.createElement('div', {className:'some_class'}, 'Content');
}

module.exports = Component;

A developer working on React components has an access only to the directory with them e.g. /src.

The question is, can he somehow add some code to any of the components to be able to fetch external resource via Node.js?

I mean if he for example would add let http = require('http'); to the component source code JS file and then change the component function like

function Component() {
    http.get('http://example.com', (contents) => {
        contents.pipe(res);
    });
}

he will receive the error

res is not defined

But still, is there a way for him to add something to the component JS file in order to fetch an external resource via Node.js as the server?

And not just using http.get() but any other way including Express.js and so on



Solution

Your question sounds like you are testing your code for security loopholes. If that is indeed your intention, I think I can report one loophole:

The Component must return an HTML element synchronously, whereas http.get (and other external fetch operations, like from a database), are asynchronous in nature. However, a developer could introduce a global variable content that is filled with an HTTP response asynchronously, but returns its current value to the ReactDOMServer.renderToStaticMarkup function. Sooner or later, it will be filled with the HTTP response and with the next request your React component will contain that response.

var content = "";
function Component() {
  http.get('http://example.com', function(res) {
    var c = "";
    res.on("data", function(chunk) {
      c += chunk.toString();
    })
    .on("end", function() {
      content = c;
    });
  });
  return React.createElement('div', {className:'some_class'}, content);
}


This Question was asked in StackOverflow by stckvrw and Answered by Heiko Thei├čen It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?