[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 框架