Node.js最重要的方面之一是具有非常迅速地实现HTTP和Https服务器和服务的能力。Node.js提供内置的http和https模块,并且它们给了你一个基本的框架来做从HTTP和HTTPS的角度来看你可能需要做的任何事情。事实上,之使用http模块来实现完整的Web服务器,这是不难做到的。
然而,http模块是相当低层次的。你可能会使用不同的模块,如express来实现完整的web服务器。http模块不提供路由,cookie,缓存等的调用。
你更有可能使用HTTP模块的地方是实现供应用程序使用的后端服务。这使得http模块成为你的工具箱中以个非常宝贵的工具。你可以创建基本的HTTP服务器,它们为在你的防火墙后面的通信提供一个接口,然后在创建一个与这些服务交互的基本的HTTP客户端。
本章主要介绍在使用http模块实现客户端和服务器时你使用到的对象。
1,处理URL
统一资源定位符(URL)充当HTTP服务器用来处理来自客户端的请求的一个地址标签。它为把一个请求发送到正确的服务器的特定端口上,并访问合适的数据提供了所有需要的信息。
一个URL可以被分解成绩个不同的组成部分,每个部分都为Web服务器如何路由和处理来自客户端的HTTP请求提供一块基本的信息。下图显示了URL及其可以被包括的组件的基本结构。不是每一个HTTP请求都包括所有的这些组件。例如,大多数请求都不包括身份验证组件,许多请求不包括查询字符串或散列位置。
http://user:pass@host.com:80/resource/path/?query=string#hash
其中各部分的含义分别是:http:协议 user:pass:身份验证 @host.com:主机名 80 端口 resource:路径名
?query=string:查询 #hash:散列
1.1,了解URL对象
来自客户端的HTTP请求包括URL字符串和在上面描述的这些信息。为了能够更有效地使用URL信息,Node.js提供了URL模块,它提供了把一个URL字符串转换成一个URL对象的功能。
要从一个URL字符串创建URL对象,把URL字符串作为第一个参数传递给下面的方法:
url.parse(urlStr,[parseQueryString],[slashesDenoteHost])
url.parse()方法将一个URL字符串作为第一个参数。parseQueryString参数是一个布尔值;如果为true,那么也吧URL的查询字符串部分解析为对象字面量。它的默认值为false。slashesDenoteHost也是一个布尔值;如果为true,那么把格式为//host/path的URL解析为{host:’host’,pathname:’/path’},而不是{pathname:’//host/path’}。它的默认值为false。
你还可以使用url.format()方法将一个URL对象转换成字符串的形式:
url.format(urlObj)
下表列出了由url.parse()创建的URL对象的属性。
属性 | 说明 |
href | 这是最初解析的完整的URL字符串 |
protocol | 请求协议,小写 |
host | URL的完整注意部分,包括端口信息,小写 |
auth | URL的身份验证信息 |
hostname | 主机的主机名部分,小写 |
port | 主机的端口信息 |
pathname | URL的路径部分(包括最初的斜线) |
search | URL的查询字符串部分,包括前导的问号 |
path | 完整路径,包括路径和搜索 |
query | 这要么是查询字符串的参数部分,要么是含有查询字符串参数和值的解析后的对象。如果parseQueryString设置为true,就是解析后的对象 |
hash | URL的散列部分,包括井号(#) |
以下是解析一个URL字符装换成一个对象,然后将其装换会字符串的例子:
var url = require('url');
var urlStr = 'http://user:pass@host.com:80/resource/path?query=string#hash';
var urlObj = url.parse(urlStr,true,false);
urlString = url.format(urlObj);
1.2,解析URL组件
url模块有用的一种功能是用与浏览器相同的方式来解析URL的组件。这可以让你在服务器端操作URL字符串,以在URL中做出调整。例如,你可能想要在处理一个请求之前更改的URL位置,因为该资源已经移动或更改了参数。
要把一个URL解析到新的位置,可以使用一下语法:
url.resolve(from,to)
from参数指定原始基础URL字符串。to参数指定你想要URL被解析到的新位置。下面的代码显示把一个URL解析到新位置的一个例子。
var url = require('url');
var originalUrl = 'http://user:pass@host.com:80/resource/path?query=string#hash';
var newResource = '/another/path?querynew';
console.log(url.resolve(originalUrl,newResource));
2,处理查询字符串和表单参数
HTTP请求通常在URL中包含查询字符串或在正文内包含参数数据来处理表单的提交。查询字符串可以从上一节所定义的URL对象获得。由表单请求发送的参数数据可以从客户端请求的正文读出。
查询字符串和表单参数都只是基本的键/值对。要在Node.js Web服务器中实际使用这些值,你需要使用querystring模块的parse()方法将字符串转换成JavaScript对象:
querystring.parse(str,[sep],[eq],[options])
str参数是查询或参数字符串。sep参数允许你指定使用的分隔符,默认的分隔符是&。eq参数允许你指定分析事使用的赋值运算符,它的默认值为=.options参数是一个具有属性maxKeys的对象,它让你能够限制生成的对象可以包含的键的数量,默认值是1000.如果把它指定为0,则表示没有任何限制。
下面是一个使用parse()来解析查询字符串的例子:
var qs = require('querystring');
var params = qs.parse("name=Border&color=red&color=blue");
3,了解请求,响应和服务器对象
要使用Node.js应用程序的http模块,你首先需要了解请求和响应对象。它们提供信息及流入,流出HTTP客户端和服务器的许多功能。当你看到这些对象的组成时,包括属性,事件和它们提供的方法,就能很容易地实现自己的HTTP服务器和客户端。
以下各节介绍ClientRequest,ServerResponse,IncomingMessage和Server对象的宗旨和行为。你将了解每种对象提供的最重要的事件,属性和方法。
3.1,http.ClientRequest对象
当你构建一个HTTP客户端时,调用http.request()使得一个ClientRequest对象在内部被创建。这个对象是为了当该请求在服务器上进展的时候来表示它。你使用ClientRequest对象来启动,监控和处理来自服务器的响应。
ClientRequest对象实现了一个Writable流,所以它提供了一个Writable流对象的所有功能。例如,你可以使用write()方法写入ClientRequest对象以及把一个Readable流用管道传输到它里面去。
要实现ClientRequest对象,可以使用一下语法来调用http.request():
http.request(options,callback)
options参数是一个对象,其属性定义了如何把客户端的HTTP请求打开并发送到服务器。下表列出了可以指定的属性,callback参数是一个回调函数,在把请求发送到服务器后,处理从服务器返回的响应时调用此回调函数。此回调函数唯一的参数是一个IncomingMessage对象,该对象是来自服务器的响应。
选项 | 说明 |
host |
请求发往的服务器的域名或IP地址 默认为localhost |
hostname | 与host相同,但对于url.parse()的支持优于host |
port | 远程服务器的端口。默认为80 |
localAddress | 网络连接绑定的本地接口 |
socketPath | Unix套接字(使用host:port或socketPath) |
method | 指定HTTP请求方法的字符串。例如,GET,POST,CONNECT,OPTIONS等。默认为GET |
path | 指定所请求的资源路径的字符串。默认为/。这也应该包括查询字符串(如果有的话)。例如:/book.html?chapter=12 |
headers |
包含请求标头的对象。例如: {‘content-length’:’750′,’content-type’:’text/plain’}s |
auth | 基本身份验证,它的形式为:user:password,用于计算Authorization头 |
agent |
Agent(代理)行为的定义。如果使用Agent,则请求默认为Connection:keep-alive。可能的值如下所示。
undefined(默认值):使用全局Agent
Agent:使用特定的Agent对象
false:禁用Agent行为 |
下面的代码显示了ClientRequest对象的基本实现:
var http = require('http');
var options = {
hostname : 'www.myserver.com',
path: '/',
port: '8080',
method : 'POST'
};
var req = http.request(options,function(response){
var str = ''
response.on('data',function(chunk){
str += chunk;
});
response.on('end',function(){
console.log(str);
});
});
req.end();
ClientRequest对象提供了几个事件,使你能够处理请求可能会遇到的各种状态。例如,你可以添加一个监听器,它在response(响应)事件由服务器的响应触发时被调用。下表列出了ClientResponse对象提供的事件。
事件 | 说明 |
response | 当从服务器接收到该请求的响应时发出。该回调处理程序接收一个IncomingMessage对象作为唯一的参数 |
socket | 当一个套接字被分配给该请求后发出 |
connect | 每当服务器响应一个由CONNECT方法发出的一个请求时发出。如果该事件未由客户端处理,那么该连接将被关闭 |
uggrade | 当服务器响应在其标头包括一个更新请求的请求时发出 |
continue | 当服务器发送一个100 Continue HTTP响应,指示客户端发送请求正文时发出 |
除了提供事件,ClientRequest对象还提供了可用于将数据写入请求,中止请求或停止请求的几种方法。下表列出了ClientRequest对象可用的方法。
方法 | 说明 |
write(chunk,[encoding]) | 把一个正文数据块(Buffer或String对象)写入请求。这可用让你的数据流入ClientRequest对象的Writable流。如果你传输正文数据,则当你创建请求时应该包括{‘Transfer-Encoding’,’chunked’}标头选项。编码参数默认为utf8 |
end([data],[encoding]) | 把可选的数据写入请求正文,然后刷新Writable流并终止该请求 |
abort() | 中止当前的请求 |
setTimeout(time,[callback]) | 为请求设置套接字超时时间 |
setNoDelay([noDelay]) | 禁用在发送数据之前缓存数据的Nagle算法。noDelay参数是一个布尔值,为true表示立即写,为false表示缓冲写入 |
setSocketKeepAlive([enable],[initialDelay]) | 启用和禁用对客户机请求的保持活动功能。enable参数默认为false,即禁用。initialDelay参数指定最后一个数据报和第一个保持活动请求之间的延迟 |
3.2,http.ServerResponse对象
当HTTP服务器接收到一个request(请求)事件时,它在内部创建ServerResponse对象。这个对象作为第二个参数被传递到request(请求)事件处理程序。你可以使用ServerRequest对象制定并发送到客户端的响应。
ServerResponse对象实现了一个Writable流,所以它提供了一个Writable流对象的所有功能。例如,你可以使用write()方法写入ServerResponse对象,也可以用管道把Readable流传入它以把数据写回客户端。
处理客户端请求时,你使用属性,事件和ServerResponse对象的方法来建立和发送标头,写入数据,以及发送响应。下表列出了在ServerResponse对象中可用的事件和属性。和在ServerResponse对象中可用的方法。
事件或属性 | 说明 |
close | 当客户端的连接在发送Response.End()来完成并刷新响应之前关闭时发出 |
headersSent | 布尔值:如果标头已被发送,为true;否则为false。这是只读的 |
sendDate | 布尔值:如果设置为true,则Date标头是自动生成的,并作为响应的一部分发送 |
statusCode |
让你无须显示地写入标头来指定响应状态码。例如:
response.statusCode = 500; |
方法 | 说明 |
writeContinue() | 发送一个HTTP/1.1 100 continue消息给客户端,请求被发送的正文内容 |
writeHead(statusCode,[reasonPhrase],[headers]) |
把一个响应标头写入请求。StatusCode参数是3位数的HTTP响应状态代码,如200,401,或500.可选的reasonPhrase是一个字符串,表示StatusCode的原因。headers是响应标头对象。例如:
response.writeHead(200,’Succrss’,{ ‘Content-Length’:body.length, ‘Content-Type’:’text/plain’ }); |
setTimeout(msecs,callback) | 设置客户端连接的套接字超时时间,以毫秒计,带有一个如果发生超时将被执行的回调函数 |
setHeader(name,value) | 设置一个特定的标头值,其中name是HTTP标头的名称,而value是标头的值 |
getHeader(name,value) | 获取一个已在响应中设置的一个HTTP标头的值 |
removeHeader(name) | 移除已在响应中设置的一个HTTP标头 |
write(chunk,[encoding]) | 写入chunk,Buffer或String对象到writable流。这仅把数据写入响应的正文部分。默认编码为utf8.如果数据被成功写入,返回true;否则,如果数据被写到用户内存,则返回false。如果它返回false,当缓冲区再次空闲时,drain事件将由Writable流发出 |
addTrailers(headers) | 将HTTP尾随标头写入响应的结束处 |
end([data],[encoding]) | 将可选的数据输出写入响应的正文,然后刷新Writable流并完成响应 |
3.3,http.IncomingMessage对象
无论是HTTP服务器还是HTTP客户端都创建IncomingMessage对象。在服务器端的客户端请求由一个IncomingMessage对象表示,而在客户端的服务器响应由一个IncomingMessage对象表示。IncomingMessage对象可同时用于两者的原因在于它们的功能基本上是相同的。
该IncomingMessage对象意味着实现了一个Readable流,让你能够吧客户端请求或服务器响应作为流源读入。这意味着它们的readable和data事件可以被监听并用来从流中读出数据。
除了由Readable类提供的功能,IncomingMessage对象还提供了在下表中列出的属性,事件和方法。这使你可以从客户端请求或服务器响应访问信息。
方法,事件和属性 | 说明 |
close | 当底层套接字被关闭时发出 |
httpVersion | 指定用于构建客户端请求/响应的HTTP版本 |
headers | 包含了随请求/回应发送的标头的一个对象 |
trailers | 包含了一个随请求/响应发送的任何trailer标头的对象 |
method | 指定用于请求/响应发送的任何trailer标头的对象 |
url | 发送到服务器的url字符串。这是可以传递到url.parse()的字符串。这个属性只在处理客户端请求的HTTP服务器中有效 |
statusCode | 指定来自服务器的3位数状态码。此属性只在处理服务器响应的HTTP客户端上有效 |
socket | 这是一个指向net.Socket对象的句柄,用来与客户端/服务器通信 |
setTimeout(msecs,callback) | 设置连接的以毫秒为单位的套接字超时时间,连同一个如果发生超时将被执行的回调函数 |
3.4,HTTP Server对象
Node.js HTTP Server对象提供了实现HTTP服务器的基本框架。它提供了一个监听端口的底层套接字和接收请求,然后发送响应给客户端连接的处理程序。当服务器正在监听时,Node.js应用程序并没有结束。
Server对象实现EventEmitter并且发出如下表列出的事件。当你实现一个HTTP服务器时,你需要处理这些事件中的至少某些或全部。例如,当收到客户端请求时,你至少需要一个事件处理程序所触发的request事件。
事件 | 说明 |
request | 每当服务器收到客户端请求时触发。回调函数应该接受两个参数。第一个参数是代表客户端请求的IncomingMessage对象,第二个参数是用来制定和发送响应的ServerResponse对象。例如: function callback(request,response){} |
connection | 当一个新的TCP流建立时触发。回调函数接收套接字作为唯一的参数。例如:function callback(socket){} |
close | 服务器关闭时触发。回调函数不接收参数 |
checkContinue | 当收到包括期待的100-continue标头的请求时触发。即使你不处理此事件,默认的事件处理程序也响应HTTP/1.1 100 Continue。例如:function callback(request,response){} |
connect | 接收到HTTP CONNECT请求时发出。callback接收request,socket, 以及head,它是一个包含隧道流的第一个包的缓冲区。例如: function callback(request,socket,head){} |
upgrade | 当客户端请求HTTP升级时发出。如果不处理这个事件,则客户端发送一个升级请求来把自己的连接关闭。callback接收request,socket,以及head,它是一个包含隧道流的第一个包的缓冲区。例如:function callback(request,socket,head){} |
clientError | 当客户端连接套接字发出一个错误时发出。callback接收error作为第一个参数,并接收socket作为第二个参数。例如: function callback(error,socket){ } |
要启动HTTP服务器,你需要首先使用createServer()方法创建一个Server对象,如下所示:
http.createServer([requestListener])
此方法返回Server对象、可选的requestListener参数是在请求事件被触发时执行的回调函数。此回调函数应该接受两个参数。第一个参数是代表客户端请求的IncomingMessage对象,第二个参数是用来制定和发送响应的ServerResponse对象。
一旦创建了Server对象,你就可以通过调用在Server对象上的listen()方法开始监听它:
listen(port,[hostname],[backlog],[callback])
这是你最有可能使用的方法。以下是这些参数的说明。
- port(端口):指定监听的端口
- hostname(主机名):当主机名将接受连接时指定。如果省略这个参数,则服务器接收直接指向任何IPV4地址(INADDR_ANY)的连接。
- backlog(积压):指定被允许进行排队的最大待处理连接数。默认值是511.
- callback(回调):指定该服务器已经开始在指定的端口上监听时,要执行的回调处理程序。
下面的代码显示了启动一个HTTP服务器并监听端口8080的一个示例。注意,请求回调处理函数被传递到createServer()方法中:
var http = require('http');
http.createServer(function(req,res){
<<handle the request and response here>>
}).listen(8080);
可以使用另外两种方法来监听文件系统的连接。第一个方法接收一个要监听的文件路径,第二个方法接受一个已经打开的文件描述符句柄:
listen(path,[callback])
listen(handle,[callback])
要使HTTP服务器停止已经开始的监听,请使用一下close()方法:
close([callback])
4,在Node.js中实现HTTP客户端和服务器
现在,你理解了ClientRequest,ServerReponse和IncomingMessage对象。你可以深入下去,并实现一些Node.js HTTP客户端和服务器。本件将引导你完成在Node.js中实现基本的HTTP客户端和服务器的过程。你将在每节实现客户端和服务器,来看看两者的相互作用
4.1,提供静态文件服务
最基本的HTTP服务器类型是一个提供静态文件服务的服务器。为了在Node.js中提供静态文件服务,你需要先启动HTTP服务器并监听端口。然后,在请求处理程序中,你需要使用fs模块在本地打开该文件,然后在响应中写入文件的内容。
下面的清单显示了一个静态文件服务器的基本实现。请注意,第5行使用createServer()创建了一个服务器,也定义了第6~15行所示的请求事件处理程序。还要注意,服务器通过调用listen()在Server对象上监听8080端口。
var fs = require('fs');
var http = require('http');
var url = require('url');
var ROOT_DIR = "html/";
http.createServer(function(req,res){
var urlObj = url.parse(req.url,true,false);
fs.readFile(ROOT_DIR + urlObj.pathname,function(err,data){
if(err){
res.writeHead(404);
res.end(JSON.stringify(err));
return;
}
res.writeHead(200);
res.end(data);
});
}).listen(8080);
要测试上面清单中的代码,可以使用任何Web浏览器,然后输入URL localhost:8080
下面的清单中显示了一个HTTP客户端的基本实现,它向服务器发送一个GET请求来检索文件内容。
var http = require('http');
var options = {
hostname:'localhost',
port:'8080',
path:'/hello.html'
};
function handleResponse(response){
var serverData = '';
response.on('data',function(chunk){
serverData += chunk;
});
response.on('end',function(){
console.log(serverData);
});
}
http.request(options,function(response){
handleResponse(response);
}).end();
如下是代码效果
4.2,实现动态的GET服务器
比起你使用Node.js Web服务器来提供静态内容,你将更经常的使用它们提供动态内容。该内容可以是动态的HTML文件或片段,JSON数据,或一些其他类型的数据。要动态地为一个GET请求提供服务,你需要在请求处理程序中实现代码,用它来动态填充要发送回客户端的数据,把它写入响应,然后调用end()来完成响应和刷新Writable流。
下面的清单显示了一个动态Web服务器的基本实现。在这个例子中,Web服务器简单地用一个动态生成的HTTP文件来响应。该示例旨在显示发送标头,建立响应,然后在一系列write()请求中发送数据的过程。
http_server_get.js 文件
var http = require('http');
var message = [
'hello World',
'From a basic Node.js server',
'Take Luck'];
http.createServer(function(req,res){
res.setHeader("Content-Type","text/html");
res.writeHead(200);
res.write('<html><head><title>Simple HTTP Server</title></head>');
res.write('<body>');
for(var idx in message){
res.write('\n<h1>' + message[idx] + '</h1>');
}
res.end('\n</body></html>');
}).listen(8080);
http_client_get.js 文件
var http = require('http');
var options = {
hostname:'localhost',
port:'8080',
};
function handleResponse(response){
var serverData = '';
response.on('data',function(chunk){
serverData += chunk;
});
response.on('end',function(){
console.log("Response Status:",response.statusCode);
console.log("Response Headers:",response.headers);
console.log(serverData);
});
}
http.request(options,function(response){
handleResponse(response);
}).end();
下面是输出:
4.3,实现POST服务器
实现一个POST服务器类似于实现一个GET服务器。事实上,为方便起见,你可能最终在同一个代码中实现它们。如果你需要使用表单提交将数据发送到服务器进行更新,POST服务器是很方便的。为了满足一个POST请求,则需要在请求处理程序中实现代码来读取POST正文的内容并处理这些内容。
一旦处理完数据,你就可以动态填充要发送回客户端的数据,把它写入响应,然后调用end()来完成响应并刷新Writable流。如同一个动态的GET服务器,POST请求的输出可能是一个网页,一个HTTP片段,JSON数据,或一些其他的数据。
下面的清单中显示了一个处理POST请求的动态Web服务的基本实现。在这个例子中,Web服务从客户端接收一个JSON字符串,它表示一个具有name和occupation属性的对象。在第4~6行的代码从请求流中读取数据,然后在第7~14行的事件处理程序中,该数据被转换为一个对象,并用于建立具有message(消息)和question(问题)属性的新对像。然后在第14~17行中,响应JSON字符串被转换为一个对象,并显示在控制台上。
http_server_post.js:
var http = require('http');
http.createServer(function(req,res){
var jsonData = "";
req.on('data',function(chunk){
jsonData += chunk;
});
req.on('end',function(){
var reqObj = JSON.parse(jsonData);
var resObj = {
message:"Hello " + reqObj.name,
question:"Are you a good "+ reqObj.occupation + "?"
};
res.writeHead(200);
res.end(JSON.stringify(resObj));
});
}).listen(8080);
var http = require('http');
var options = {
host:'127.0.0.1',
path:'/',
port:'8080',
method:'POST'
};
function readJSONResponse(response){
var responseData = '';
response.on('data',function(chunk){
responseData += chunk;
});
response.on('end',function(){
var dataObj = JSON.parse(responseData);
console.log("Raw Response: " + responseData);
console.log("message: " + dataObj.message);
console.log("Question: " + dataObj.question);
});
}
var req = http.request(options,readJSONResponse);
req.write('{"name":"Bilbo","occupation":"Burglar"}');
req.end();
http_client_post.js:
var http = require('http');
var options = {
host:'127.0.0.1',
path:'/',
port:'8080',
method:'POST'
};
function readJSONResponse(response){
var responseData = '';
response.on('data',function(chunk){
responseData += chunk;
});
response.on('end',function(){
var dataObj = JSON.parse(responseData);
console.log("RawResponse: " + responseData);
console.log("Message: " + dataObj.message);
console.log("Question:" + dataObj.question);
});
}
var req = http.request(options,readJSONResponse);
req.write('{"name":"Bilbo","occupation":"Burglar"}');
req.end();
效果:
4.4,与外部源交互
Node.js中的http服务的一个常见用途是访问外部系统获得的数据来满足客户端的请求。各种外部系统提供了可以以各种方式使用的数据。在这个例子中,代码连接到openweathermap.org API来检索有关一个城市的天气信息。为了保持例子简单,来自openweathermap.org的输出以原始格式被推送到浏览器。在现实中,你可能会需要将数据块输送到自己的网页,窗口控件,或数据响应中。
下面的代码清单显示了同时接受GET和POST请求的Web服务的实现。对于GET请求,则返回一个带有一个表单的简单网页,它允许用户提交一个城市的名字。然后在POST请求中,城市名称被访问,且Node.js Web客户端启动并远程连接到openweathermap.org检索该城市的天气信息。之后这些信息连同原来的网页表单被遗弃返回到服务器。
本示例与前一示例之间的最大区别在于,Web服务器还实现了一个本地Web客户端连接到外部服务,并获得数据,以完成响应。Web服务器在第35~49行实现。
var http = require('http');
var url = require('url');
var qstring = require('querystring');
function sendResponse(weatherData,res){
var page = '<html><head><title>External Example</title></head>' +
'<body>' +
'<form method="post">' +
'City:<input name="city"><br>' +
'<input type="submit" value="Get Weather">' +
'</form>';
if(weatherData){
page += '<h1>Weather Info</h1><p>' + weatherData +'</p>';
}
page += '</body></html>';
res.end(page);
}
function parseWeather(weatherResponse,res){
var weatherData = '';
weatherResponse.on('data',function(chunk){
weatherData += chunk;
});
weatherResponse.on('end',function(){
sendResponse(weatherData,res);
});
}
function getWeather(city,res){
var options = {
host:'api.openweathermap.org',
path:'/data/2.5/weather?q=' + city
};
http.request(options,function(weatherResponse){
parseWeather(weatherResponse,res);
}).end();
}
http.createServer(function(req,res){
console.log(req.method);
if(req.method == "post"){
var reqData = '';
req.on('data',function(chunk){
reqData += chunk;
});
req.on('end',function(){
var postParams = qstring.parse(reqData);
getWeather(postParams.city,res);
});
}else{
sendResponse(null,res);
}
}).listen(8080);