# Node HTTP 教程

> 原文： [http://zetcode.com/javascript/http/](http://zetcode.com/javascript/http/)

Node HTTP 教程展示了如何使用带有 HTTP 模块的 JavaScript 创建 HTTP 服务器和客户端应用。

## HTTP

HTTP 是一个 Node.js 模块，可用于在 JavaScript 中创建 HTTP 服务器和客户端应用。 流行的 JavaScript 框架（包括 Express 和 HapiJS）建立在 HTTP 模块的顶部。

本教程教您 HTTP 交互的基础知识。 要创建真实的 Web 应用，我们应该使用完整的 Web 框架，例如 JavaScript 的 Express 或 PHP 的 Symfony。

## 安装 HTTP

首先，我们安装 HTTP 模块。

```js
$ node -v
v11.5.0

```

我们使用 Node.js 11.5 版。

```js
$ npm init -y

```

我们启动一个新的 Node.js 应用。

```js
$ npm i http

```

我们使用`npm i http`命令安装 HTTP。

## Node HTTP 简单服务器

使用`createServer()`创建服务器应用。

`simple.js`

```js
const http = require('http');

http.createServer((req, res) => {

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write('Hello there');
    res.end();

}).listen(8080);

console.log('server running on port 8080');

```

该示例创建了一个非常简单的 HTTP 服务器，该服务器将文本消息发送到客户端。 服务器在端口 8080 上运行。

```js
const http = require('http');

```

首先，我们包括 HTTP 模块。

```js
http.createServer((req, res) => {

```

我们使用`createServer()`函数创建一个 Web 应用。 它接受一个接收两个参数的处理函数：请求和响应对象。

```js
res.writeHead(200, { 'Content-Type': 'text/plain' });

```

使用`writeHead()`方法，我们将标头写入响应。 我们指定状态码和内容类型。

```js
res.write('Hello there');

```

我们将数据写入响应。

```js
res.end();

```

我们将回复发送给客户。

```js
$ node simple.js
server running on port 8080

```

我们启动服务器。

```js
$ curl localhost:8080
Hello there

```

使用`curl`工具，我们向服务器创建 GET 请求并接收消息。

## Node HTTP 发送 JSON

在下一个示例中，我们创建一个发送 JSON 响应的服务器。 JSON（JavaScript 对象表示法）是一种轻量级的数据交换格式。

`send_json.js`

```js
const http = require('http');

const server = http.createServer((req, res) => {

    if (req.url == '/now') {

        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.write(JSON.stringify({ now: new Date() }));
        res.end();

    } else {

        res.end('Invalid request');
    }
});

server.listen(8080);

console.log('server running on port 8080');

```

应用通过以 JSON 发送当前日期来响应`/now`请求路径。

```js
if (req.url == '/now') {

```

我们检查请求 URL 是否等于`/now`。

```js
res.writeHead(200, { 'Content-Type': 'application/json' });

```

我们通知客户端，我们在标头中使用适当的内容类型发送 JSON 响应。

```js
res.write(JSON.stringify({ now: new Date() }));

```

我们将 JSON 中的当前日期写入响应中。

## Node HTTP 发送 HTML

接下来，我们将向客户端发送 HTML 数据。

`send_html.js`

```js
const http = require('http');

const server = http.createServer(function (req, res) {

    if (req.url == '/') {

        res.writeHead(200, { 'Content-Type': 'text/html' });

        res.write('<html><body><p>This is home page.</p></body></html>');
        res.end();

    } else if (req.url == "/contact") {

        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write('<html><body><p>This is contact page</p></body></html>');
        res.end();

    } else if (req.url == "/admin") {

        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write('<html><body><p>This is admin page</p></body></html>');
        res.end();

    } else {

        res.end('Invalid request');
    }

});

server.listen(8080);

console.log('server running on port 8080');

```

我们指定`text/html`内容类型，并将 HTML 标记写入响应。

> **注意**：在实际应用中，我们不会在响应中编写 HTML 代码。 我们使用模板。

## Node HTTP 查询参数

客户端可以通过向 URL 添加查询参数来与服务器通信。

`query_params.js`

```js
const http = require('http');
const url = require('url');

http.createServer((req, res) => {

    let q = url.parse(req.url, true).query;

    let msg = `${q.name} is ${q.age} years old`;

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.write(msg);
    res.end();

}).listen(8080);

console.log('server running on port 8080');

```

在该示例中，服务器以根据查询参数构建的消息作为响应。

```js
const url = require('url');

```

为了解析查询参数，我们使用`url`模块。

```js
let q = url.parse(req.url, true).query;

```

我们得到具有值的查询对象。

```js
let msg = `${q.name} is ${q.age} years old`;

```

我们根据查询参数构建消息。

```js
$ curl "localhost:8080/?name=Peter&age=34"
Peter is 34 years old

```

启动服务器后，我们使用`curl`创建请求。 我们指定查询参数。

## Node HTTP 服务器

下面的示例创建一个更复杂的 HTTP 服务器。 `docs`子目录中有三个 HTML 文件。

`docs/about.html`

```js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>About page</title>
</head>
<body>

    <p>This is about page.</p>

</body>
</html>

```

这是`about.html`文件。

`docs/contact.html`

```js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact page</title>
</head>
<body>

    <p>This is contact page.</p>

</body>
</html>

```

这是`contact.html`文件。

`docs/index.html`

```js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home page</title>
</head>
<body>

    <p>
        This is home page.
    </p>
</body>
</html>

```

这是`index.html`文件。

`http_server.js`

```js
const http = require('http');
const fs = require('fs');
const url = require('url');

const server = http.createServer((req, res) => {

   let pathname = url.parse(req.url).pathname;

   console.log(`Request for ${pathname} received`);

   if (pathname == '/') {

      pathname = '/index.html';
   }

   fs.readFile('docs/' + pathname.substr(1), (err, data) => {

      if (err) {

         console.error(err);

         res.writeHead(404, { 'Content-Type': 'text/plain' });
         res.write('404 - file not found');

      } else {

         res.writeHead(200, { 'Content-Type': 'text/html' });
         res.write(data.toString());
      }

      res.end();
   });
});

server.listen(8080);

console.log('server running on port 8080');

```

```js
const fs = require('fs');

```

我们使用`fs`模块读取 HTML 文件。

该示例从文件系统读取 HTML 文件。

```js
let pathname = url.parse(req.url).pathname;

```

我们确定路径名，即要加载的文件名。

```js
if (pathname == '/') {

    pathname = '/index.html';
}

```

对于根页面，我们发送`index.html`。

```js
fs.readFile('docs/' + pathname.substr(1), (err, data) => {

```

使用`readFile()`方法，我们读取 HTML 文件的内容。

```js
if (err) {

  console.error(err);

  res.writeHead(404, { 'Content-Type': 'text/plain' });
  res.write('404 - file not found');

} ...

```

发生错误时，我们会将 404 代码发送给客户端。

```js
} else {

  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.write(data.toString());
}

```

如果找到并读取了文件，我们会将文件的内容发送给客户端。

## Node HTTP GET 请求

我们也可以使用 HTTP 模块来创建客户端请求。

`http_get.js`

```js
const http = require('http');

const options = {
    hostname: 'webcode.me',
    port: 80,
    path: '/',
    method: 'GET'
};

const req = http.request(options, (res) => {

    console.log(`statusCode: ${res.statusCode}`);

    res.on('data', (d) => {

        process.stdout.write(d);
    });
});

req.on('error', (err) => {

    console.error(err);
});

req.end();

```

该示例向`webcode.me`创建 HTTP GET 请求。

```js
const options = {
    hostname: 'webcode.me',
    port: 80,
    path: '/',
    method: 'GET'
};

```

这些选项包含所生成请求的主机名，端口，路径和 HTTP 方法。

```js
const req = http.request(options, (res) => {

```

使用`request()`生成请求。

```js
res.on('data', (d) => {

    process.stdout.write(d);
});

```

我们不断将传入的数据写入数据事件处理器中的控制台。

```js
$ node http_get.js
statusCode: 200
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>

    <p>
          Hello there. How are you?
    </p>

</body>
</html>

```

这是输出。

另外，我们可以使用`get()`方法。

`http_get.js`

```js
const http = require('http')

const req = http.get({ host: 'webcode.me', path: '/' }, (res) => {

    // Continuously update stream with data
    let content = '';

    res.on('data', (chunk) => {
        content += chunk;
    });

    res.on('end', () => {

        console.log(content);
    });
});

req.end();

```

我们生成对同一网站的 GET 请求。

```js
// Continuously update stream with data
let content = '';

res.on('data', (chunk) => {
    content += chunk;
});

```

我们不断将检索到的数据块添加到`content`变量中。

```js
res.on('end', () => {

    console.log(content);
});

```

最后，我们将变量打印到控制台。

## Node HTTP POST 请求

下面的示例向`httpbin.org`网站创建 POST 请求。 这是一个免费的网站，我们可以在其中测试我们的请求。 由于站点使用 HTTPS 协议，因此我们使用`https`模块。

`http_post.js`

```js
const https = require('https');

let payload = JSON.stringify({
    "name": "Peter",
    "age": 34
});

let headers = {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(payload, 'utf8')
};

let options = {
    host: 'httpbin.org',
    port: 443,
    path: '/post',
    method: 'POST',
    headers: headers
};

let reqPost = https.request(options, (res) => {
    console.log("status code: ", res.statusCode);

    res.on('data', (chunks) => {

        process.stdout.write(chunks);
    });
});

reqPost.write(payload);
reqPost.end();

reqPost.on('error', (err) => {

    console.error(err);
});

```

该示例将数据发送到测试网站。 服务器以包含我们已发送的有效负载的数据进行响应。

```js
const https = require('https');

```

我们使用`https`模块。

```js
payload = JSON.stringify({
    "name": "Peter",
    "age": 34
});

```

这是要发送的有效负载。

```js
let headers = {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(payload, 'utf8')
};

```

这些是标题。 我们发送 JSON 数据。 我们指定内容的长度。

```js
let options = {
    host: 'httpbin.org',
    port: 443,
    path: '/post',
    method: 'POST',
    headers: headers
};

```

这些是 POST 请求的选项。 HTTPS 标准端口为 443。

```js
let reqPost = https.request(options, (res) => {
    console.log("status code: ", res.statusCode);

    res.on('data', (chunks) => {

        process.stdout.write(chunks);
    });
});

```

在 post 调用的数据事件处理器中，我们将数据写入控制台。

```js
reqPost.write(payload);

```

我们将有效载荷数据写入 POST 请求。

```js
reqPost.end();

```

请求已发送。

在本教程中，我们使用了 JavaScript HTTP 模块。

列出 [JavaScript 教程](/all/#js)。