I was surprised that I did not find this so quickly by a Google search, so I hereby write it up and hope it will help someone else. I did find some things that will help so I will assemble these together.
Of course, the first task is to build a HTTP server, easily done by copying the sample from the node.js website. To get the request parameters:
and to send the outgoing HTTP request:
Of course, there is a bit of functional programming to make the pieces work together asynchronously. I will use CoffeeScript since it should make the functional programming much easier to understand.
I: Get parameters from HTTP request
var http = require('http');
var url = require('url');
http.createServer(function (req, res) {
// http://stackoverflow.com/questions/6912584/how-to-get-get-query-string-variables-in-node-js
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World query: ' + JSON.stringify(query) + '\n');
}).listen(8082, '62.212.66.2');
on server: node test1.js
and from a test client (my Mac):
$ curl "http://62.212.66.2:8082/findNearByWeatherJSON?lat=43&lng=-2&username=demo"
Hello World query: {"lat":"43","lng":"-2","username":"demo"}
II. Add outgoing HTTP request
On server: npm install -g js2coffee and js2coffee test1.js > test1.coffee
http = require("http")
url = require("url")
http.createServer((req, res) ->
url_parts = url.parse(req.url, true)
query = url_parts.query
res.writeHead 200,
"Content-Type": "text/plain"
res.end "Hello World query: " + JSON.stringify(query) + "\n"
).listen 8082, "62.212.66.2"
But first we want to add the outgoing HTTP request from the Javascript sample in http://docs.nodejitsu.com/articles/HTTP/clients/how-to-create-a-HTTP-request:
var http = require('http');
var url = require('url');
http.createServer(function (req1, res) {
// http://stackoverflow.com/questions/6912584/how-to-get-get-query-string-variables-in-node-js
var url_parts = url.parse(req1.url, true);
var query = url_parts.query;
var options = {
host: 'api.geonames.org',
path: '/findNearByWeatherJSON?lat=43&lng=-2&username=demo'
};
callback = function(response) {
var str = '';
//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
//the whole response has been recieved, so we just print it out here
response.on('end', function () {
console.log(str);
});
}
http.request(options, callback).end();
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World query: ' + JSON.stringify(query) + '\n');
}).listen(8082, '62.212.66.2');
On the server: node test1.js
Upon receiving a request from the client:
{"weatherObservation":{"clouds":"few clouds","weatherCondition":"n/a","observation":"LESO 170730Z 17003KT 140V200 9999 FEW048 BKN069 07/02 Q1020","windDirection":170,"ICAO":"LESO","elevation":8,"countryCode":"ES","lng":-1.8,"temperature":"7","dewPoint":"2","windSpeed":"03","humidity":70,"stationName":"San Sebastian / Fuenterrabia","datetime":"2012-04-17 07:30:00","lat":43.35,"hectoPascAltimeter":1020}}
So there are now two problems: (i) including the actual coordinates from the client and (ii) putting the received data into the response. Both of these problems will be easier to solve in the CoffeeScript version.
III. Putting it all together
On server (again): js2coffee test1.js > test1.coffee
http = require("http")
url = require("url")
http.createServer((req1, res) ->
url_parts = url.parse(req1.url, true)
query = url_parts.query
options =
host: "api.geonames.org"
path: "/findNearByWeatherJSON?lat=43&lng=-2&username=demo"
callback = (response) ->
str = ""
response.on "data", (chunk) ->
str += chunk
response.on "end", ->
console.log str
http.request(options, callback).end()
res.writeHead 200,
"Content-Type": "text/plain"
res.end "Hello World query: " + JSON.stringify(query) + "\n"
).listen 8082, "62.212.66.2"
So the next steps are:
- put the incoming request data into the outgoing weather request
- Indent the res.writeHead and res.end code by 4 spaces, to include these in the callback function, and keep the http.request statement outside the callback block
- Of course, JSON.parse the response data, and
- return the JSON response with the desired data, using the application/JSON content type
So here is the complete CoffeeScript:
http = require("http")
url = require("url")
http.createServer((req1, res) ->
url_parts = url.parse(req1.url, true)
query = url_parts.query
options =
host: "api.geonames.org"
path: "/findNearByWeatherJSON?lat=#{query.lat}&lng=#{query.lng}&username=demo"
callback = (response) ->
str = ""
response.on "data", (chunk) ->
str += chunk
response.on "end", ->
console.log str
data = JSON.parse str
res.writeHead 200,
"Content-Type": "application/json"
res.end JSON.stringify
temperature: data.weatherObservation.temperature
http.request(options, callback).end()
).listen 8082, "62.212.66.2"
Compile to Javascript and run on Node, here are the results from the client:
{"temperature":"8"}
Of course, it would be nice to include the locality of the weather station, cleanup the log output, etc. etc.