http模块是Node.js中的核心模块之一,它主要用于创建服务器和处理HTTP协议的请求和响应。

一、服务器基本概念

服务器(Server):服务器是一种为其他计算机网络服务的计算机或系统,提供大量的储存空间,强大的数据处理能力和带宽。所谓服务,是指服务器在网络中起到一个中心角色,为其它以它为中心的计算机(也即客户机)提供各种服务,包括数据服务、应用服务、存储服务等。例如,网站的所有数据信息都保存在服务器上,当我们在浏览网页时,实际上就是向服务器请求相关数据。

IP地址:即互联网协议地址(Internet Protocol Address),是指互联网上每一个网络接口的标识。每个连接到互联网的设备都有一个唯一的IP地址,包含了这台设备在网络上的位置信息。举例,192.168.0.1就是一个IPv4地址的例子。

域名(Domain Name):是Internet上的一串标识符,是IP地址的一种表现形式,作为寻址的一种方式。比如,我们常用的www.google.com就是一个域名。因为数字地址(IP地址)难以记忆,人们为了方便使用,就设计了与之对应的、由字符组成的地址名,这就是域名。

端口号(Port Number):是设备使用的一个虚拟数据表结构,用来区分不同的服务或者应用程序。传输控制协议(TCP)和用户数据报协议(UDP)指定的端口号达66536个。端口号和IP地址一起提供了网络上的设备和应用程序的确切地址。例如,当我们在浏览器中访问一个网站时,默认的端口号是80,若要访问特定的端口,如8080端口,那访问地址就会是www.example.com:8080。

二、使用node中的http模块创建基本web服务器

在Node.js中,我们可以通过内置的http模块来创建一个web服务器。下面给出一个基本的web服务器的创建过程以及代码分析:

步骤

  1. 导入HTTP模块:第一步是包含http模块。如下所示:

    // 引入 Node.js 自带的 http 模块
    var http = require('http');
    
  2. 创建服务器:使用http模块的createServer方法创建服务器。如下所示:

    // 使用 http 模块创建 HTTP 服务器
    var server = http.createServer(function (req, res) {
      // 设置 HTTP 头部,状态码为 200,文件类型为html,字符集为UTF-8
      res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});
    
      // 发送响应数据
      res.end('Hello World\n');
    });
    
  3. 监听端口:然后我们绑定服务器到8000端口,使用listen方法。如下所示:

    // 让服务器监听 8000 端口
    server.listen(8000);
    
    console.log('Server running at http://127.0.0.1:8000/');
    

总体代码分析:

以下是完整的代码和注释:

// 引入 Node.js 自带的 http 模块
var http = require('http');

// 使用 http 模块创建 HTTP 服务器
var server = http.createServer(function (req, res) {
  // 设置 HTTP 头部,状态码为 200,文件类型为html,字符集为UTF-8
  res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'});

  // 发送响应数据 "Hello World"
  res.end('Hello World\n');
});

// 让服务器监听 8000 端口
server.listen(8000);

console.log('Server running at http://127.0.0.1:8000/');

以上,就是Node.js如何通过http模块创建一个基本的web服务器。

三、req请求对象

在Node.js中,通过http模块创建的基本Web服务器的req对象是一个IncomingMessage的实例,它表示一个来自客户端(通常是浏览器)的http请求。该对象包含此http请求的所有请求头、请求参数以及其他请求相关的信息。它可以用来获取请求的方法、URL、头部等信息,以便于服务器进行相应的处理。

一些常用的req对象属性如下:

  • req.headers:一个对象,包含了请求的头部信息。
  • req.method:一个字符串,表示请求的方法,如’GET’,'POST’等。
  • req.url:一个字符串,表示请求的URL。
  • req.body:如果请求是POST类型,则可以通过该属性读取请求体的内容,但需要配合使用‘body-parser’模块。

以下是一段简单的Node.js代码,创建一个Web服务器,并在每个请求中打印出请求的头部信息、请求方法以及请求URL:

// 引入http模块
const http = require('http');

// 通过http模块创建一个web服务器
const server = http.createServer((req, res) => {
    // 请求的头部信息
    console.log('Headers:', req.headers);

    // 请求的方法
    console.log('Method:', req.method);

    // 请求的URL
    console.log('URL:', req.url);

    // 设置响应头部信息
    res.writeHead(200, {'Content-Type': 'text/plain'});

    // 发送响应数据 "Hello World"
    res.end('Hello World\n');
});

// 设置服务器监听8080端口,同时设置监听函数,在服务器启动后打印一行日志。
server.listen(8080, () => {
    console.log('Server running at http://127.0.0.1:8080');
});

以上代码中,‘http.createServer((req, res) => {…})’中的函数是一个请求处理函数,它在每次有新的http请求时被调用。函数的参数’req’和’res’分别是Node.js为我们创建好的表示请求和响应的对象,我们可以通过它们来处理http请求和发送http响应。

四、res响应对象

在Node.js中,http模块是创建一个本地服务器的主要方式。res对象,也就是响应(response)对象,是我们用来回应来自客户端,也就是用户的请求的。你可以通过它来设置你将要返回给用户的内容,比如文本信息,HTML文档,数据等等。

常用的res对象的属性和方法包括:

  1. res.writeHead(): 设置HTTP头信息。它接受两个参数,第一个是HTTP状态码,第二个是一个包含头信息的对象。

  2. res.write(): 对响应内容的主体进行写入操作。

  3. res.end(): 告诉服务器,所有的响应头和响应主体都已经被发送,服务器应该考虑这条消息已经完成。如果不调用这个函数,客户端会一直等待服务器的响应,直到超时。

  4. res.setHeader(): 设置HTTP头部信息。

下面是一个创建基本Web服务器的例子,使用了这些操作:

const http = require('http'); // 导入http模块

http
  .createServer(function (req, res) { // 创建一个服务器,该函数会在每次有请求时被调用
    res.writeHead(200, { 'Content-Type': 'text/plain' }); // 设置HTTP头信息,200表示成功,返回的内容为文本类型
    res.write('Hello World'); // 响应主体写入"Hello World"这段文本
    res.end(); // 响应结束,返回给客户端
  })
  .listen(8080); // 服务器开始监听8080端口

注意: 我们的目标是返回一个 “Hello World” 的文本给客户端,所以已经调用res.write('Hello World')将其写入响应主体。经过调用res.end(),这个响应就宣告结束,然后会返回给客户端。而客户端(通常是一个Web浏览器)在接收到响应后,就会展示给用户看。

五、根据不同的请求,响应不同的内容

在NodeJS中,我们可以通过http模块来创建一个Web服务器。服务器可以监听客户端的请求,对请求作出处理,并返回对应的响应。

这里是一个简单的使用NodeJS创建的Web服务器示例:

const http = require('http');
const fs = require('fs'); // 文件系统模块,用于读取文件

http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'}); 
  res.end('Hello World\n'); 
}).listen(8000, 'localhost');
console.log('Server running at http://localhost:8000/');

服务器调用http.createServer()方法,并传入一个匿名函数。该函数接收两个参数:request和response。我们可以调用response对象的方法来指定HTTP响应的相关属性,并最终通过res.end()返回响应的内容。

对于不同类型的响应内容,我们需要根据情况指定不同的响应头,主要是Content-Type。以下是一些常见的Content-Type:

  • 文本(text/plain)
  • HTML(text/html)
  • 图片(image/png, image/jpeg)
  • JSON(application/json)

对于不同的请求路径,我们可以通过req.url访问。通常,我们会根据不同的URL路径来返回不同的内容。例如:

http.createServer((req, res) => {
  if(req.url == '/'){
    res.writeHead(200, {'Content-Type': 'text/html'}); 
    res.end('<h1>Welcome to the homepage!</h1>'); 
  } else if (req.url == '/data') {
    res.writeHead(200, {'Content-Type': 'application/json'}); 
    res.end(JSON.stringify({message: 'Hello, this is data page!'})); 
  } else {
    res.writeHead(404, {'Content-Type': 'text/plain'}); 
    res.end('Not found'); 
  }
}).listen(8000, 'localhost');

对于读取文件并返回,我们需要使用到fs模块:

http.createServer((req, res) => {
  fs.readFile('path-to-your-file', (err, data) => {
    if(err){
      res.writeHead(404, {'Content-Type': 'text/plain'}); 
      res.end('Not found'); 
    } else {
      res.writeHead(200, {'Content-Type': 'text/html'}); // 假设文件为HTML
      res.end(data); 
    }
  });
}).listen(8000, 'localhost');

下面举个完整应用案例
下列代码展示了在 Node 中使用 http 模块创建一个可以基于请求的 URL 路径和请求的 HTTP 方法返回不同响应的 Web 服务器。该服务器可以返回文本、图片、HTML 文件 和 JSON 数据。

// 导入需要的模块
const http = require('http');
const fs = require('fs');
const path = require('path');

// 创建 HTTP 服务器
const server = http.createServer((req, res) => {
    // 根据请求的 URL 和 HTTP 方法返回不同的内容
    if (req.url === '/' && req.method === 'GET') {
        // 如果请求是 GET 方法并且 URL 是‘/’,返回‘Hello, World!’文本
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('Hello, World!');
    } else if (req.url === '/image' && req.method === 'GET') {
        // 如果请求是 GET 方法并且 URL 是‘/image’,返回一张图片
        res.writeHead(200, { 'Content-Type': 'image/jpeg' });
        fs.createReadStream(path.join(__dirname, 'image.jpeg')).pipe(res);
    } else if (req.url === '/index' && req.method === 'GET') {
        // 如果请求是 GET 方法并且 URL 是‘/index’,返回一个 HTML 文件
        res.writeHead(200, { 'Content-Type': 'text/html' });
        fs.createReadStream(path.join(__dirname, 'index.html')).pipe(res);
    } else if (req.url === '/data' && req.method === 'GET') {
        // 如果请求是 GET 方法并且 URL 是‘/data’,返回一个 JSON 数据
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ message: "Hello, World!" }));
    } else {
        // 如果没有匹配到任何路由,返回 404
        res.writeHead(404);
        res.end();
    }
});

// 启动 HTTP 服务器,并监听 3000 端口
server.listen(3000);

在这个例子中,我们使用了 Node.js 的 http.createServer() 函数创建了一个服务器,并通过 server.listen() 启动它。我们根据请求的 urlmethod 使用 if-else 语句来处理不同的路由。

我们使用了 Node.js 的 fs 模块读取文件内容,fs.createReadStream() 创建一个到指定文件的可读流,并通过管道流将文件内容直接发送给响应对象。

我们使用了 Node.js 的 path 模块的 path.join() 函数来生成文件的绝对路径。

我们使用 res.writeHead() 来设置响应的状态码和头信息,然后使用 res.end() 来结束响应并发送内容。我们还可以使用 JSON.stringify() 将 JavaScript 对象转换为 JSON 字符串。

请记住,你需要在代码相同的目录下有一个名为 image.jpeg 的图片文件,和一个名为 index.html 的 HTML 文件才能使这个例子正常工作。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐