Node.js Http模塊

2021-09-15 16:32 更新

基本用法

處理GET請(qǐng)求

Http模塊主要用于搭建HTTP服務(wù)。使用Node.js搭建HTTP服務(wù)器非常簡(jiǎn)單。

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模塊。然后,調(diào)用http模塊的createServer方法,創(chuàng)造一個(gè)服務(wù)器實(shí)例,將它賦給變量http。

ceateServer方法接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的request參數(shù)是一個(gè)對(duì)象,表示客戶端的HTTP請(qǐng)求;response參數(shù)也是一個(gè)對(duì)象,表示服務(wù)器端的HTTP回應(yīng)。response.writeHead方法表示,服務(wù)器端回應(yīng)一個(gè)HTTP頭信息;response.end方法表示,服務(wù)器端回應(yīng)的具體內(nèi)容,以及回應(yīng)完成后關(guān)閉本次對(duì)話。最后的listen(8080)表示啟動(dòng)服務(wù)器實(shí)例,監(jiān)聽(tīng)本機(jī)的8080端口。

將上面這幾行代碼保存成文件app.js,然后用node調(diào)用這個(gè)文件,服務(wù)器就開(kāi)始運(yùn)行了。

$ node app.js

這時(shí)命令行窗口將顯示一行提示“Server running at port 8080.”。打開(kāi)瀏覽器,訪問(wèn)http://localhost:8080,網(wǎng)頁(yè)顯示“Hello world!”。

上面的例子是當(dāng)場(chǎng)生成網(wǎng)頁(yè),也可以事前寫好網(wǎng)頁(yè),存在文件中,然后利用fs模塊讀取網(wǎng)頁(yè)文件,將其返回。

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.');

下面的修改則是根據(jù)不同網(wǎng)址的請(qǐng)求,顯示不同的內(nèi)容,已經(jīng)相當(dāng)于做出一個(gè)網(wǎng)站的雛形了。

var http = require("http");

http.createServer(function(req, res) {

  // 主頁(yè)
  if (req.url == "/") {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end("Welcome to the homepage!");
  }

  // About頁(yè)面
  else if (req.url == "/about") {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end("Welcome to the about page!");
  }

  // 404錯(cuò)誤
  else {
    res.writeHead(404, { "Content-Type": "text/plain" });
    res.end("404 error! File not found.");
  }

}).listen(8080, "localhost");

回調(diào)函數(shù)的req(request)對(duì)象,擁有以下屬性。

  • url:發(fā)出請(qǐng)求的網(wǎng)址。
  • method:HTTP請(qǐng)求的方法。
  • headers:HTTP請(qǐng)求的所有HTTP頭信息。

處理POST請(qǐng)求

當(dāng)客戶端采用POST方法發(fā)送數(shù)據(jù)時(shí),服務(wù)器端可以對(duì)data和end兩個(gè)事件,設(shè)立監(jiān)聽(tīng)函數(shù)。

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事件會(huì)在數(shù)據(jù)接收過(guò)程中,每收到一段數(shù)據(jù)就觸發(fā)一次,接收到的數(shù)據(jù)被傳入回調(diào)函數(shù)。end事件則是在所有數(shù)據(jù)接收完成后觸發(fā)。

對(duì)上面代碼稍加修改,就可以做出文件上傳的功能。

"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");
});

發(fā)出請(qǐng)求

get()

get方法用于發(fā)出get請(qǐng)求。

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方法用于發(fā)出HTTP請(qǐng)求,它的使用格式如下。

http.request(options[, callback])

request方法的options參數(shù),可以是一個(gè)對(duì)象,也可以是一個(gè)字符串。如果是字符串,就表示這是一個(gè)URL,Node內(nèi)部就會(huì)自動(dòng)調(diào)用url.parse(),處理這個(gè)參數(shù)。

options對(duì)象可以設(shè)置如下屬性。

  • host:HTTP請(qǐng)求所發(fā)往的域名或者IP地址,默認(rèn)是localhost。
  • hostname:該屬性會(huì)被url.parse()解析,優(yōu)先級(jí)高于host。
  • port:遠(yuǎn)程服務(wù)器的端口,默認(rèn)是80。
  • localAddress:本地網(wǎng)絡(luò)接口。
  • socketPath:Unix網(wǎng)絡(luò)套接字,格式為host:port或者socketPath。
  • method:指定HTTP請(qǐng)求的方法,格式為字符串,默認(rèn)為GET。
  • path:指定HTTP請(qǐng)求的路徑,默認(rèn)為根路徑(/)??梢栽谶@個(gè)屬性里面,指定查詢字符串,比如/index.html?page=12。如果這個(gè)屬性里面包含非法字符(比如空格),就會(huì)拋出一個(gè)錯(cuò)誤。
  • headers:一個(gè)對(duì)象,包含了HTTP請(qǐng)求的頭信息。
  • auth:一個(gè)代表HTTP基本認(rèn)證的字符串user:password
  • agent:控制緩存行為,如果HTTP請(qǐng)求使用了agent,則HTTP請(qǐng)求默認(rèn)為Connection: keep-alive,它的可能值如下:
    • undefined(默認(rèn)):對(duì)當(dāng)前host和port,使用全局Agent。
    • Agent:一個(gè)對(duì)象,會(huì)傳入agent屬性。
    • false:不緩存連接,默認(rèn)HTTP請(qǐng)求為Connection: close。
  • keepAlive:一個(gè)布爾值,表示是否保留socket供未來(lái)其他請(qǐng)求使用,默認(rèn)等于false。
  • keepAliveMsecs:一個(gè)整數(shù),當(dāng)使用KeepAlive的時(shí)候,設(shè)置多久發(fā)送一個(gè)TCP KeepAlive包,使得連接不要被關(guān)閉。默認(rèn)等于1000,只有keepAlive設(shè)為true的時(shí)候,該設(shè)置才有意義。

request方法的callback參數(shù)是可選的,在response事件發(fā)生時(shí)觸發(fā),而且只觸發(fā)一次。

http.request()返回一個(gè)http.ClientRequest類的實(shí)例。它是一個(gè)可寫數(shù)據(jù)流,如果你想通過(guò)POST方法發(fā)送一個(gè)文件,可以將文件寫入這個(gè)ClientRequest對(duì)象。

下面是發(fā)送POST請(qǐng)求的一個(gè)例子。

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()必須被調(diào)用,即使沒(méi)有在請(qǐng)求體內(nèi)寫入任何數(shù)據(jù),也必須調(diào)用。因?yàn)檫@表示已經(jīng)完成HTTP請(qǐng)求。

發(fā)送過(guò)程的任何錯(cuò)誤(DNS錯(cuò)誤、TCP錯(cuò)誤、HTTP解析錯(cuò)誤),都會(huì)在request對(duì)象上觸發(fā)error事件。

搭建HTTPs服務(wù)器

搭建HTTPs服務(wù)器需要有SSL證書。對(duì)于向公眾提供服務(wù)的網(wǎng)站,SSL證書需要向證書頒發(fā)機(jī)構(gòu)購(gòu)買;對(duì)于自用的網(wǎng)站,可以自制。

自制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

上面的命令生成兩個(gè)文件:ert.pem(證書文件)和 key.pem(私鑰文件)。有了這兩個(gè)文件,就可以運(yùn)行HTTPs服務(wù)器了。

Node.js提供一個(gè)https模塊,專門用于處理加密訪問(wèn)。

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服務(wù)器與HTTP服務(wù)器的最大區(qū)別,就是createServer方法多了一個(gè)options參數(shù)。運(yùn)行以后,就可以測(cè)試是否能夠正常訪問(wèn)。

curl -k https://localhost:8000

模塊屬性

(1)HTTP請(qǐng)求的屬性

  • headers:HTTP請(qǐng)求的頭信息。
  • url:請(qǐng)求的路徑。

模塊方法

(1)http模塊的方法

  • createServer(callback):創(chuàng)造服務(wù)器實(shí)例。

(2)服務(wù)器實(shí)例的方法

  • listen(port):?jiǎn)?dòng)服務(wù)器監(jiān)聽(tīng)指定端口。

(3)HTTP回應(yīng)的方法

  • setHeader(key, value):指定HTTP頭信息。
  • write(str):指定HTTP回應(yīng)的內(nèi)容。
  • end():發(fā)送HTTP回應(yīng)。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)