I have recently wrote a JavaScript web application that depended on AJAX and a Java driven back end. The back end was a standard RESTful Web service running an a Glassfish server. Before I started working on the application a designer was hired to make the HTML/CSS layout that was desired. As I got further into the development process and the moving parts started to change the CSS also needed to change. This proposed a problem for us mainly because all of the data ( and the html elements needed to display it) that were needed to populate each page had to be requested from the Web service. Typically what I would do is log in to the web application running on the test server fired up firebug and use the HTML/CSS edit feature to get the CSS to where I needed it to be. Alternatively, I would save the website and open the HTML and CSS pages locally and edit from there. Any CSS changes would then get committed to the repo. However, this wasn’t a good enough way for the designer. The designer wanted to put the repo on their localhost and simply run the application on their local server. This of course caused a CORS error because an XHR request could not be made from localhost to a remote server.
To solve this problem the designer could have got a local copy of the back end working on his localhost as well. However that would involve mysql, eclipse and glassfish to be configured correctly. Not really ideal. So I went out in search for another solution. After talking to some people I decided to use node.js. Havent yet worked with node I wasn’t quite sure of what I was going to do. Some people said i needed a Proxy some said i needed Middleware but at the end of it all I just needed a simple server and a client.
The Structure
The idea is for a server to listen to the requests coming in from your localhost on a particular port. This means that the URL of the XHR requests has to be changed to localhost:portnumber. Once the request is captured, a dummy client will make the same exact request but instead of the client being your localhost, it will be a node client whose domain is the same as the domain of the back end. Create a client using the domain of the back end. I never really found any documentation of what the createClient function accepted so let me show you what I used:
var aclient = http.createClient(80, 'backendurl.com');
The next step is to create a server that listens on a particular port. This is the same port i mentioned above. Ensure that this port is not being used by another application running on your computer otherwise you will get a weird port not available exception. Now, in the function that you pass in when you create the server you need to capture the request, get the needed data and make a similar request with a new url. You also need to figure out what the request method is. This is important because sometimes there will be an OPTIONS method sent which is basically a way of the browser testing if CORS is allowed.
if (req.method === 'OPTIONS') {
// add needed headers
var headers = {};
headers["Access-Control-Allow-Origin"] = "*";
headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
headers["Access-Control-Allow-Credentials"] = true;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Access-Control-Allow-Headers"] = "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept";
// respond to the request
res.writeHead(200, headers);
res.end();
} else if (req.method === 'GET') { // no data is coming
// use the client you created to make a request, this request will basically
// need all of the information captured in this GET request coming from your localhost:portnumber
var clientrequest = aclient.request(req.method, '/api' + req.url, {
'host': 'backendurl.com',
'authorization': req.headers['authorization'],
'content-type': 'application/json',
'connection': 'keep-alive',
});
clientrequest.end();
var msg = "", clietheaders;
// get the response from the back-end
clientrequest.on('response', function (clientresponse) {
clientheaders = clientresponse.headers;
clientresponse.on('data', function (chunk) {
msg += chunk;
});
});
setTimeout(function () {
// send the data you just received from the back end back to you
// client application on localhost
res.writeHead(200, clientheaders);
res.write(msg);
res.end();
}, 500); // wait a bit just in case we don't have all of the chunks of data
}