[TOC]
## 基本用法
### 处理GET请求
Http模块主要用于搭建HTTP服务。使用Node.js搭建HTTP服务器非常简单。
~~~
var http = require('http');
http.createServer(function (request, response){
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8080, "127.0.0.1");
console.log('Server running on port 8080.');
~~~
上面代码第一行`var http = require("http")`,表示加载http模块。然后,调用http模块的createServer方法,创造一个服务器实例,将它赋给变量http。
ceateServer方法接受一个函数作为参数,该函数的request参数是一个对象,表示客户端的HTTP请求;response参数也是一个对象,表示服务器端的HTTP回应。response.writeHead方法表示,服务器端回应一个HTTP头信息;response.end方法表示,服务器端回应的具体内容,以及回应完成后关闭本次对话。最后的listen(8080)表示启动服务器实例,监听本机的8080端口。
将上面这几行代码保存成文件app.js,然后用node调用这个文件,服务器就开始运行了。
~~~
$ node app.js
~~~
这时命令行窗口将显示一行提示“Server running at port 8080.”。打开浏览器,访问[http://localhost:8080,网页显示“Hello](http://localhost:8080%EF%BC%8C%E7%BD%91%E9%A1%B5%E6%98%BE%E7%A4%BA%E2%80%9CHello/) world!”。
上面的例子是当场生成网页,也可以事前写好网页,存在文件中,然后利用fs模块读取网页文件,将其返回。
~~~
var http = require('http');
var fs = require('fs');
http.createServer(function (request, response){
fs.readFile('data.txt', function readData(err, data) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(data);
});
}).listen(8080, "127.0.0.1");
console.log('Server running on port 8080.');
~~~
下面的修改则是根据不同网址的请求,显示不同的内容,已经相当于做出一个网站的雏形了。
~~~
var http = require("http");
http.createServer(function(req, res) {
// 主页
if (req.url == "/") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end("Welcome to the homepage!");
}
// About页面
else if (req.url == "/about") {
res.writeHead(200, { "Content-Type": "text/html" });
res.end("Welcome to the about page!");
}
// 404错误
else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("404 error! File not found.");
}
}).listen(8080, "localhost");
~~~
回调函数的req(request)对象,拥有以下属性。
* url:发出请求的网址。
* method:HTTP请求的方法。
* headers:HTTP请求的所有HTTP头信息。
### 处理POST请求
当客户端采用POST方法发送数据时,服务器端可以对data和end两个事件,设立监听函数。
~~~
var http = require('http');
http.createServer(function (req, res) {
var content = "";
req.on('data', function (chunk) {
content += chunk;
});
req.on('end', function () {
res.writeHead(200, {"Content-Type": "text/plain"});
res.write("You've sent: " + content);
res.end();
});
}).listen(8080);
~~~
data事件会在数据接收过程中,每收到一段数据就触发一次,接收到的数据被传入回调函数。end事件则是在所有数据接收完成后触发。
对上面代码稍加修改,就可以做出文件上传的功能。
~~~
"use strict";
var http = require('http');
var fs = require('fs');
var destinationFile, fileSize, uploadedBytes;
http.createServer(function (request, response) {
response.writeHead(200);
destinationFile = fs.createWriteStream("destination.md");
request.pipe(destinationFile);
fileSize = request.headers['content-length'];
uploadedBytes = 0;
request.on('data', function (d) {
uploadedBytes += d.length;
var p = (uploadedBytes / fileSize) * 100;
response.write("Uploading " + parseInt(p, 0) + " %\n");
});
request.on('end', function () {
response.end("File Upload Complete");
});
}).listen(3030, function () {
console.log("server started");
});
~~~
## 发出请求
### get()
get方法用于发出get请求。
~~~
function getTestPersonaLoginCredentials(callback) {
return http.get({
host: 'personatestuser.org',
path: '/email'
}, function(response) {
var body = '';
response.on('data', function(d) {
body += d;
});
response.on('end', function() {
var parsed = JSON.parse(body);
callback({
email: parsed.email,
password: parsed.pass
});
});
});
},
~~~
### request()
request方法用于发出HTTP请求,它的使用格式如下。
~~~
http.request(options[, callback])
~~~
request方法的options参数,可以是一个对象,也可以是一个字符串。如果是字符串,就表示这是一个URL,Node内部就会自动调用`url.parse()`,处理这个参数。
options对象可以设置如下属性。
* host:HTTP请求所发往的域名或者IP地址,默认是localhost。
* hostname:该属性会被`url.parse()`解析,优先级高于host。
* port:远程服务器的端口,默认是80。
* localAddress:本地网络接口。
* socketPath:Unix网络套接字,格式为host:port或者socketPath。
* method:指定HTTP请求的方法,格式为字符串,默认为GET。
* path:指定HTTP请求的路径,默认为根路径(/)。可以在这个属性里面,指定查询字符串,比如`/index.html?page=12`。如果这个属性里面包含非法字符(比如空格),就会抛出一个错误。
* headers:一个对象,包含了HTTP请求的头信息。
* auth:一个代表HTTP基本认证的字符串`user:password`。
* agent:控制缓存行为,如果HTTP请求使用了agent,则HTTP请求默认为`Connection: keep-alive`,它的可能值如下:
* undefined(默认):对当前host和port,使用全局Agent。
* Agent:一个对象,会传入agent属性。
* false:不缓存连接,默认HTTP请求为`Connection: close`。
* keepAlive:一个布尔值,表示是否保留socket供未来其他请求使用,默认等于false。
* keepAliveMsecs:一个整数,当使用KeepAlive的时候,设置多久发送一个TCP KeepAlive包,使得连接不要被关闭。默认等于1000,只有keepAlive设为true的时候,该设置才有意义。
request方法的callback参数是可选的,在response事件发生时触发,而且只触发一次。
`http.request()`返回一个`http.ClientRequest`类的实例。它是一个可写数据流,如果你想通过POST方法发送一个文件,可以将文件写入这个ClientRequest对象。
下面是发送POST请求的一个例子。
~~~
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(postData);
req.end();
~~~
注意,上面代码中,`req.end()`必须被调用,即使没有在请求体内写入任何数据,也必须调用。因为这表示已经完成HTTP请求。
发送过程的任何错误(DNS错误、TCP错误、HTTP解析错误),都会在request对象上触发error事件。
## 搭建HTTPs服务器
搭建HTTPs服务器需要有SSL证书。对于向公众提供服务的网站,SSL证书需要向证书颁发机构购买;对于自用的网站,可以自制。
自制SSL证书需要OpenSSL,具体命令如下。
~~~
openssl genrsa -out key.pem
openssl req -new -key key.pem -out csr.pem
openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem
rm csr.pem
~~~
上面的命令生成两个文件:ert.pem(证书文件)和 key.pem(私钥文件)。有了这两个文件,就可以运行HTTPs服务器了。
Node.js提供一个https模块,专门用于处理加密访问。
~~~
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
var a = https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
~~~
上面代码显示,HTTPs服务器与HTTP服务器的最大区别,就是createServer方法多了一个options参数。运行以后,就可以测试是否能够正常访问。
~~~
curl -k https://localhost:8000
~~~
## 模块属性
(1)HTTP请求的属性
* headers:HTTP请求的头信息。
* url:请求的路径。
## 模块方法
(1)http模块的方法
* createServer(callback):创造服务器实例。
(2)服务器实例的方法
* listen(port):启动服务器监听指定端口。
(3)HTTP回应的方法
* setHeader(key, value):指定HTTP头信息。
* write(str):指定HTTP回应的内容。
* end():发送HTTP回应。
- 第一章 导论
- 1.1 前言
- 1.2 为什么学习JavaScript?
- 1.3 JavaScript的历史
- 第二章 基本语法
- 2.1 语法概述
- 2.2 数值
- 2.3 字符串
- 2.4 对象
- 2.5 数组
- 2.6 函数
- 2.7 运算符
- 2.8 数据类型转换
- 2.9 错误处理机制
- 2.10 JavaScript 编程风格
- 第三章 标准库
- 3.1 Object对象
- 3.2 Array 对象
- 3.3 包装对象和Boolean对象
- 3.4 Number对象
- 3.5 String对象
- 3.6 Math对象
- 3.7 Date对象
- 3.8 RegExp对象
- 3.9 JSON对象
- 3.10 ArrayBuffer:类型化数组
- 第四章 面向对象编程
- 4.1 概述
- 4.2 封装
- 4.3 继承
- 4.4 模块化编程
- 第五章 DOM
- 5.1 Node节点
- 5.2 document节点
- 5.3 Element对象
- 5.4 Text节点和DocumentFragment节点
- 5.5 Event对象
- 5.6 CSS操作
- 5.7 Mutation Observer
- 第六章 浏览器对象
- 6.1 浏览器的JavaScript引擎
- 6.2 定时器
- 6.3 window对象
- 6.4 history对象
- 6.5 Ajax
- 6.6 同域限制和window.postMessage方法
- 6.7 Web Storage:浏览器端数据储存机制
- 6.8 IndexedDB:浏览器端数据库
- 6.9 Web Notifications API
- 6.10 Performance API
- 6.11 移动设备API
- 第七章 HTML网页的API
- 7.1 HTML网页元素
- 7.2 Canvas API
- 7.3 SVG 图像
- 7.4 表单
- 7.5 文件和二进制数据的操作
- 7.6 Web Worker
- 7.7 SSE:服务器发送事件
- 7.8 Page Visibility API
- 7.9 Fullscreen API:全屏操作
- 7.10 Web Speech
- 7.11 requestAnimationFrame
- 7.12 WebSocket
- 7.13 WebRTC
- 7.14 Web Components
- 第八章 开发工具
- 8.1 console对象
- 8.2 PhantomJS
- 8.3 Bower:客户端库管理工具
- 8.4 Grunt:任务自动管理工具
- 8.5 Gulp:任务自动管理工具
- 8.6 Browserify:浏览器加载Node.js模块
- 8.7 RequireJS和AMD规范
- 8.8 Source Map
- 8.9 JavaScript 程序测试
- 第九章 JavaScript高级语法
- 9.1 Promise对象
- 9.2 有限状态机
- 9.3 MVC框架与Backbone.js
- 9.4 严格模式
- 9.5 ECMAScript 6 介绍
- 附录
- 10.1 JavaScript API列表
- 草稿一:函数库
- 11.1 Underscore.js
- 11.2 Modernizr
- 11.3 Datejs
- 11.4 D3.js
- 11.5 设计模式
- 11.6 排序算法
- 草稿二:jQuery
- 12.1 jQuery概述
- 12.2 jQuery工具方法
- 12.3 jQuery插件开发
- 12.4 jQuery.Deferred对象
- 12.5 如何做到 jQuery-free?
- 草稿三:Node.js
- 13.1 Node.js 概述
- 13.2 CommonJS规范
- 13.3 package.json文件
- 13.4 npm模块管理器
- 13.5 fs 模块
- 13.6 Path模块
- 13.7 process对象
- 13.8 Buffer对象
- 13.9 Events模块
- 13.10 stream接口
- 13.11 Child Process模块
- 13.12 Http模块
- 13.13 assert 模块
- 13.14 Cluster模块
- 13.15 os模块
- 13.16 Net模块和DNS模块
- 13.17 Express框架
- 13.18 Koa 框架