nodejs--(一)http模板篇
Nodejs http模块可以创建服务器应用实例,也能发送http请求
1.http.get(options[, callback])
发送简单Get请求,并响应
- var http=require('http');
- //get 请求外网
- http.get('http://www.gongjuji.net',function(req,res){
- var html='';
- req.on('data',function(data){
- html+=data;
- });
- req.on('end',function(){
- console.info(html);
- });
- });
2.http.request(options[, callback]) // 使用详细配置,发送Get或Post请求
发送Post实例:注http请求头使用headers指定
- var http=require('http');
- var querystring=require('querystring');
- //发送 http Post 请求
- var postData=querystring.stringify({
- msg:'中文内容'
- });
- var options={
- hostname:'www.gongjuji.net',
- port:80,
- path:'/',
- method:'POST',
- headers:{
- //'Content-Type':'application/x-www-form-urlencoded',
- 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
- 'Content-Length':Buffer.byteLength(postData)
- }
- }
- var req=http.request(options, function(res) {
- console.log('Status:',res.statusCode);
- console.log('headers:',JSON.stringify(res.headers));
- res.setEncoding('utf-8');
- res.on('data',function(chun){
- console.log('body分隔线---------------------------------\r\n');
- console.info(chun);
- });
- res.on('end',function(){
- console.log('No more data in response.********');
- });
- });
- req.on('error',function(err){
- console.error(err);
- });
- req.write(postData);
- req.end();
发送Get请求实例:
- //发送Get请求
- var http=require('http');
- var querystring=require('querystring');
- var data={
- age:13,
- time:new Date().getTime()
- };
- var content=querystring.stringify(data);
- var options={
- hostname:'www.gongjuji.net',
- port:80,
- path:'/',
- method:'GET'
- }
- //创建请求
- var req=http.request(options,function(res){
- console.log('STATUS:'+res.statusCode);
- console.log('HEADERS:'+JSON.stringify(res.headers));
- res.setEncoding('utf-8');
- res.on('data',function(chunk){
- console.log('数据片段分隔-----------------------\r\n');
- console.log(chunk);
- });
- res.on('end',function(){
- console.log('响应结束********');
- });
- });
- req.on('error',function(err){
- console.error(err);
- });
- req.end();
参数说明:
options can be an object or a string. If options is a string, it is automatically parsed with url.parse().
Options:
protocol: Protocol to use. Defaults to'http:'.host: A domain name or IP address of the server to issue the request to. Defaults to'localhost'.hostname: Alias forhost. To supporturl.parse()hostnameis preferred overhost.family: IP address family to use when resolvinghostandhostname. Valid values are4or6. When unspecified, both IP v4 and v6 will be used.port: Port of remote server. Defaults to 80.localAddress: Local interface to bind for network connections.socketPath: Unix Domain Socket (use one of host:port or socketPath).method: A string specifying the HTTP request method. Defaults to'GET'.path: Request path. Defaults to'/'. Should include query string if any. E.G.'/index.html?page=12'. An exception is thrown when the request path contains illegal characters. Currently, only spaces are rejected but that may change in the future.headers: An object containing request headers.auth: Basic authentication i.e.'user:password'to compute an Authorization header.agent: ControlsAgentbehavior. When an Agent is used request will default toConnection: keep-alive. Possible values:undefined(default): usehttp.globalAgentfor this host and port.Agentobject: explicitly use the passed inAgent.false: opts out of connection pooling with an Agent, defaults request toConnection: close.
一,开篇分析
首先“Http”这个概念大家应该比较熟悉了,它不是基于特定语言的,是一个通用的应用层协议,不同语言有不同的实现细节,但是万变不离其宗,思想是相同的,
NodeJS作为一个宿主运行环境,以JavaScript为宿主语言,它也有自己实现的一套标准,这篇文章我们就一起来学习一下 “Http模块” 。但是作为前提来说,
希望大家可以先阅读一下官网提供的api,有一个前置了解,这样就方便多了,以下是Http部分的api概览:
HTTP
http.STATUS_CODES
http.createServer([requestListener])
http.createClient([port], [host])
Class: http.Server
事件 : 'request'
事件: 'connection'
事件: 'close'
Event: 'checkContinue'
事件: 'connect'
Event: 'upgrade'
Event: 'clientError'
server.listen(port, [hostname], [backlog], [callback])
server.listen(path, [callback])
server.listen(handle, [callback])
server.close([callback])
server.maxHeadersCount
server.setTimeout(msecs, callback)
server.timeout
Class: http.ServerResponse
事件: 'close'
response.writeContinue()
response.writeHead(statusCode, [reasonPhrase], [headers])
response.setTimeout(msecs, callback)
response.statusCode
response.setHeader(name, value)
response.headersSent
response.sendDate
response.getHeader(name)
response.removeHeader(name)
response.write(chunk, [encoding])
response.addTrailers(headers)
response.end([data], [encoding])
http.request(options, callback)
http.get(options, callback)
Class: http.Agent
new Agent([options])
agent.maxSockets
agent.maxFreeSockets
agent.sockets
agent.freeSockets
agent.requests
agent.destroy()
agent.getName(options)
http.globalAgent
Class: http.ClientRequest
Event 'response'
Event: 'socket'
事件: 'connect'
Event: 'upgrade'
Event: 'continue'
request.write(chunk, [encoding])
request.end([data], [encoding])
request.abort()
request.setTimeout(timeout, [callback])
request.setNoDelay([noDelay])
request.setSocketKeepAlive([enable], [initialDelay])
http.IncomingMessage
事件: 'close'
message.httpVersion
message.headers
message.rawHeaders
message.trailers
message.rawTrailers
message.setTimeout(msecs, callback)
message.method
message.url
message.statusCode
message.socket
让我们先从一个简单例子开始,创建一个叫server.js的文件,并写入以下代码:
var http = require('http') ;
var server = http.createServer(function(req,res){
res.writeHeader(200,{
'Content-Type' : 'text/plain;charset=utf-8' // 添加charset=utf-8
}) ;
res.end("Hello,大熊!") ;
}) ;
server.listen(8888) ;
console.log("http server running on port 8888 ...") ;
(node server.js)以下是运行结果:

二,细节分析实例
具体看一下这个小例子:
(1行):通过"require"引入NodeJS自带的"http"模块,并且把它赋值给http变量。
(2行):调用http模块提供的函数:"createServer" 。这个函数会返回一个新的web服务器对象。
参数 "requestListener" 是一个函数,它将会自动加入到 "request" 事件的监听队列。
当一个request到来时,Event-Loop会将这个Listener回调函数放入执行队列, node中所有的代码都是一个一个从执行队列中拿出来执行的。
这些执行都是在工作线程上(Event Loop本身可以认为在一个独立的线程中,我们一般不提这个线程,而将node称呼为一个单线程的执行环境),
所有的回调都是在一个工作线程上运行。
我们在再来看一下"requestListener"这个回调函数,它提供了两个参数(request,response),
每次收到一个请求时触发。注意每个连接又可能有多个请求(在keep-alive的连接中)。
"request"是http.IncomingMessage的一个实例。"response"是http.ServerResponse的一个实例。
一个http request对象是可读流,而http response对象则是可写流。
一个"IncomingMessage"对象是由http.Server或http.ClientRequest创建的,
并作为第一参数分别传递给"request"和"response"事件。
它也可以被用来访问应答的状态,头文件和数据。
它实现了 "Stream" 接口以及以下额外的事件,方法和属性。(具体参考api)。
(3行):“writeHeader”,使用 "response.writeHead()" 函数发送一个Http状态200和Http头的内容类型(content-type)。
向请求回复响应头。"statusCode"是一个三位是的HTTP状态码,例如 404 。最后一个参数,"headers",是响应头的内容。
举个栗子:
var body = 'hello world' ;
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain'
}) ;
注意:Content-Length 是以字节(byte)计算,而不是以字符(character)计算。
之前的例子原因是字符串 “Hello World !” 只包含了单字节的字符。
如果body包含了多字节编码的字符,就应当使用Buffer.byteLength()来确定在多字节字符编码情况下字符串的字节数。
需要进一步说明的是Node不检查Content-Lenth属性和已传输的body长度是否吻合。
statusCode是一个三位是的HTTP状态码, 例如:"404" 。这里要说的是 "http.STATUS_CODES" ,全部标准"Http"响应状态码的集合和简短描述都在里面。
如下是源码参考:
var STATUS_CODES = exports.STATUS_CODES = {
100 : 'Continue',
101 : 'Switching Protocols',
102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
200 : 'OK',
201 : 'Created',
202 : 'Accepted',
203 : 'Non-Authoritative Information',
204 : 'No Content',
205 : 'Reset Content',
206 : 'Partial Content',
207 : 'Multi-Status', // RFC 4918
300 : 'Multiple Choices',
301 : 'Moved Permanently',
302 : 'Moved Temporarily',
303 : 'See Other',
304 : 'Not Modified',
305 : 'Use Proxy',
307 : 'Temporary Redirect',
400 : 'Bad Request',
401 : 'Unauthorized',
402 : 'Payment Required',
403 : 'Forbidden',
404 : 'Not Found',
405 : 'Method Not Allowed',
406 : 'Not Acceptable',
407 : 'Proxy Authentication Required',
408 : 'Request Time-out',
409 : 'Conflict',
410 : 'Gone',
411 : 'Length Required',
412 : 'Precondition Failed',
413 : 'Request Entity Too Large',
414 : 'Request-URI Too Large',
415 : 'Unsupported Media Type',
416 : 'Requested Range Not Satisfiable',
417 : 'Expectation Failed',
418 : 'I\'m a teapot', // RFC 2324
422 : 'Unprocessable Entity', // RFC 4918
423 : 'Locked', // RFC 4918
424 : 'Failed Dependency', // RFC 4918
425 : 'Unordered Collection', // RFC 4918
426 : 'Upgrade Required', // RFC 2817
500 : 'Internal Server Error',
501 : 'Not Implemented',
502 : 'Bad Gateway',
503 : 'Service Unavailable',
504 : 'Gateway Time-out',
505 : 'HTTP Version not supported',
506 : 'Variant Also Negotiates', // RFC 2295
507 : 'Insufficient Storage', // RFC 4918
509 : 'Bandwidth Limit Exceeded',
510 : 'Not Extended' // RFC 2774
};
节选自,Nodejs源码 ”http.js“ 143行开始。
其实从客户端应答结果也不难看出:

(6行):”response.end“------当所有的响应报头和报文被发送完成时这个方法将信号发送给服务器。服务器会认为这个消息完成了。
每次响应完成之后必须调用该方法。如果指定了参数 “data” ,就相当于先调用 “response.write(data, encoding) ” 之后再调用 “response.end()” 。
(8行):”server.listen(8888)“ ------ 服务器用指定的句柄接受连接,绑定在特定的端口。
以上就是一个比较详细的分析过程,希望有助于加深理解,代码虽然不多,但是重在理解一些细节机制,以便日后高效的开发NodeJS应用。
三,实例
除了可以使用"request"对象访问请求头数据外,还能把"request"对象当作一个只读数据流来访问请求体数据。
这是一个"POST"请求的例子:
http.createServer(function (request, response) {
var body = [];
console.log(request.method) ;
console.log(request.headers) ;
request.on('data', function (chunk) {
body.push(chunk);
}) ;
request.on('end', function () {
body = Buffer.concat(body) ;
console.log(body.toString()) ;
});
}).listen(8888) ;
下是一个完整的“Http”请求数据内容。
POST / HTTP/1.1
User-Agent: curl/7.26.0
Host: localhost
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded
Hello World
四,总结一下
(1),理解 "Http" 概念。
(2),熟练使用 "Http" 相关的api。
(3),注意细节的把控,比如:“POST,GET” 之间的处理细节。
(4),"requestListener"的理解。
(5),强调一个概念:一个http request对象是可读流,而http response对象则是可写流 。
nodejs--(一)http模板篇的更多相关文章
- 10-C++远征之模板篇-学习笔记
C++远征之模板篇 将会学到的内容: 模板函数 & 模板类 -> 标准模板类 友元函数 & 友元类 静态数据成员 & 静态成员函数 运算符重载: 一切皆有可能 友元函数 ...
- 《深入浅出WPF》笔记——模板篇
原文:<深入浅出WPF>笔记--模板篇 我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照. 一.认识模板 1.1WPF菜鸟看模板 前面的记录有提过,控件主要是算法 ...
- 学习篇:NodeJS中的模板引擎:jade
NodeJS 模板引擎作用:生成页面 在node常用的模板引擎一般是 1.jade --破坏式的.侵入式.强依赖(对原有的html体系不友好,走自己的一套体系)2.ejs --温和的.非侵入式的.弱依 ...
- NodeJs学习之API篇
学习nodeJS的API在对于使用nodeJS来进行编程的是十分重要的,所以首先就要去学习看看,相关的node的模块,来看一看相关的内容和可用性. 正文篇: nodeJS的API学习之路.(这里我们将 ...
- nodejs根据word模板生成文档(方法二)
[推荐该方法,模板比较简洁] 1,代码, 这里采用的模块为 docxtemplater 和 open-docxtemplater-image-module,均为开源(docxtemplater 有收费 ...
- ASP.NET MVC学习之模型模板篇
一.前言 如果你使用ASP.NET MVC制作后台一定会爱上它的EditorForModal.DisplayForModal和LabelForModal方法,因为这些方法可以将模型直接变成对应的标签, ...
- 【nodejs】jade模板入门
使用jetbrians webstom创建空项目 1.创建package.json 引用依赖配置 { "name": "demojade", "des ...
- nodejs+express +jade模板引擎 新建项目
先 安装 nodejsiDEAAM 2015/7/16 22:47:25然后安装 npm install expressiDEAAM 2015/7/16 22:47:35然后安装 npm instal ...
- C++学习笔记之模板篇
title: C++学习笔记之模板篇 tags: c++,c,模板,vector,friend,static,运算符重载,标准模板 --- 一.模板 不管是函数模板还是类模板,在未初始化前都是不占用内 ...
随机推荐
- 如何找到java对应的c/c++源码
很多时候java经常被c鄙视,因为c说我是你的基础,但java竟然有如此强的生命力就必然有其存在的价值.本文不探讨各种开发语言的优劣,仅仅介绍如何找到java对应c/c++实现的源码.当我们追究一个j ...
- Shell在大数据时代的魅力:从一道百度大数据面试题想到的点滴
对于在Linux下开发的同学来说,Shell可以说是一种基本功. 对于运维的同学来说,Shell可以说是一种必备的技能,而且应该要非常熟练的书写Shell.对于Release Team,软件配置管理的 ...
- C++中友元详解
问题的提出 我们已知道类具备封装和信息隐 藏的特性.只有类的成员函数才能访问类的私有成员,程式中的其他函数是无法访问私有成员的.非成员函数能够访问类中的公有成员,但是假如将数据成员都定义 为公有的,这 ...
- Android程序崩溃异常处理框架
目前我已经把框架放在了github了,地址如下:https://github.com/msdx/android-crash 使用方法见github上面的README.md. 本项目相关jar包已发布在 ...
- 使用Hash函数和MAC产生伪随机数
基于Hash函数的PRNG 流程非常类似于对称密码的CTR工作模式 算法的伪码如下 m = ⌈n/outlen⌉ data = V W = the null String for i = 1 to m ...
- mysql进阶(二十五)解决数据库NO CONNECTION问题
解决数据库NO CONNECTION问题 前言 数据库版本类型:Mysql5.5 在应用程序连接数据库时,提示数据库连接失败.打开数据库查看,显示如下. 究其原因,是因为mysql服务出现了问题,重启 ...
- Hash存储机制 - HashMap原理 HashSet原理
HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...
- mongoDB常见的查询索引(三)
1. _id索引 _id索引是绝大多数集合默认建立的索引 对于每个插入的数据,MongoDB会自动生成一条唯一的_id字段. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- Dynamics CRM ADFS及IFD部署后延长系统注销时间
Dynamics CRM 部署IFD后,一段时间后登陆状态会失效,系统会提示让你重新登陆,可以通过延长失效时间来规避 在 powershell中执行如下指令 Set-ADFSRelyingPartyT ...
- (NO.00002)iOS游戏精灵战争雏形(一)
原本想做一个复杂点的平面动作游戏,可以觉得还是有点把握不了.还是先从简单的原型开始吧. 构思中的精灵战争(SpriteWar)是一个类似FC时代的小游戏,可以造兵,可以捕获敌兵.原本还想加上保卫老巢的 ...