通过JavaScript学习HTTP通信

首先

本文旨在提供学习基本知识以制作Web应用程序的学习文章。主要内容包括:

    • windows上でExcelVBA等、プログラミングの基礎知識は持っているものの

 

    • Linuxなどサーバは全く扱ったことがなくバックエンドサーバが全くのブラックボックスで

 

    Webブラウザの挙動がよくわからず、何を使ってどこをどう見れば理解していることになるのか不安

对于这样的人群而言。

首先,我们将实现一个Web服务器来确认HTTP通信的实体。


構建開發環境

将Web服务器安装在Windows PC上。为了创建Web服务器,需要安装处理器。

Nodejs (只需一个选项):

Node.js是用于执行JavaScript的运行时环境。

    • nodejs公式からwindows用のパッケージをダウンロード

 

    • 展開して実行

 

    • コマンドプロンプトを開いてnodeと入力

 

    終了は.exit

视觉工作室代码(VSCode)

VSCode是一种集成开发环境,适用于各种编程语言。它有许多方便的插件。以下是我推荐的插件。

    • Bracket Pair Colorizer2

 

    • Debugger for Chrome

 

    • (Emacs Keymap)

 

    • Git graph

 

    • indent-rainbow

 

    Japanese-language-pack

使用Node.js进行HTTP通信

首先,从官方文件开始。购买书籍是之后的事情(基本原则)。

监听端口

在计算机中,操作系统提供了”通信端口”作为进行通信的资源。官方示例代码使用的端口号是3000。

(1) 使用 VSCode 打开一个新的工作空间;点击“文件”,然后选择“命名并保存工作空间”;将其保存为 httpserver。

我将新建一个工作空间。

(2) 编辑文件;文件>新建文件。

我会创建一个新的文件来编写Web服务器程序。

这是一个在端口3000上监听HTTP通信连接的Web服务器程序,它是一个展示”你好世界”在Web浏览器上的示例程序。

样本程序将Content-Type HTTP头设置为MIME类型为’text/plain’,并在HTTP主体中设置了”Hello World”字符串。

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

(3) 保存; 文件>另存为
(4) 执行nodejs程序; 运行>开始调试>Node.js

スクリーンショット 2020-06-17 18.01.54.png

(5)通过网络浏览器访问Web服务器;启动Chrome > 输入http://localhost:3000 > 显示“Hello world”。

スクリーンショット 2020-06-17 18.06.32.png
スクリーンショット 2020-06-17 18.08.25.png

服务器端调试

在VSCode上,您可以设置断点来暂停执行nodejs程序。

(1) 设置断点
(2) 在 Web 浏览器中输入 http://localhost:3000,会在 VSCode 上停止,使用设置的断点。
(3) 从断点处进行步进执行/继续。


客户端调试

Web浏览器在进行两种类型的通信。一种是向Web服务器发出请求的通信,另一种是接收并响应的通信。在Chrome浏览器中,您可以选择菜单按钮>更多选项>开发者工具>网络。

スクリーンショット 2020-06-17 18.19.37.png

(1) 验证HTTP请求实体; 在Web浏览器中输入http://localhost:3000 > 选择请求通信(本地主机) > 选择Headers选项卡 > 选择General > 关注请求URL

スクリーンショット 2020-06-17 18.24.41.png
    • Headers > Response Headers > view source

 

    Headers > Request Headers > view source

点击此view source链接,您可以查看解析之前的通信内容。

スクリーンショット 2020-06-17 18.22.20.png

(3)HTTP状态码

    • おなじみの200, 404, 500などあります。詳しくはRFCを参照のこと

 

    • Webサーバに接続に成功して、レスポンス通信が受け取れたら200と思ってください

 

    • 接続に成功しても、サーバ側でエラーが生じた場合は400番台や500番台のステータスコードが返ってきます

 

    接続に失敗したら、そもそもHTTP通信が始められなかったということです

实习:网页服务器的实施

通过逐步修改服务器端的Node.js程序,我们可以理解HTTP通信的实际情况。

HTTP头文件Content-Type与HTTP主体的相关性以及Web浏览器的解释。

MIME类型:纯文本类型

HTTP通信基本上是发送和接收文本数据。

(1) 输出写入()

当你修改了server.js文件后,在调试运行菜单中点击旋转箭头的刷新按钮,会自动停止调试进程、保存文件、重新加载并开始调试,一系列操作将被一次性完成。

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
  res.write('Hello World');
  res.end();
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

(2) 反复

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
  for(var i = 0; i < 5; i++)
    res.write('Hello World');
  res.end();
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

(3) 即使写了之后,并不意味着立即进行通信。(重要)

    • res.write行にブレークポイントを仕掛けておく

 

    • http://localhost:3000/でアクセス

 

    • ブレークポイントで止まったら、ステップ実行

 

    res.end()で初めてレスポンス通信が開始していることがわかるでしょう

MIME类型: 文本/HTML

(1) 若HTTP头部为text/html,则HTTP主体的内容为HTML文档。

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/html');  // MIME-type(2)
  res.write('<html><body><strong>Hello world</strong></body></html>')
  res.end('');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
スクリーンショット 2020-06-18 09.25.29.png

网页浏览器将其解释为HTML文档,并突出显示了”Hello world”。

如果HTTP请求头中的MIME类型为text/plain,但HTTP主体是HTML,那会怎样呢?

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
  res.write('<html><body><strong>Hello world</strong></body></html>')
  res.end('');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
スクリーンショット 2020-06-18 09.23.26.png

即使是HTML文档,在以text/plain发送时,Web浏览器不会将其解释为HTML文档。通过HTTP响应通信中的setHeader()方法设置的HTTP头信息,可以理解为这会改变Web浏览器的行为。

在HTTP头部中,可以指定Web浏览器的行为。例如,在下载文件时,可以使用Content-Disposition头部。我们稍后会详细讨论这个问题。


使用从文件系统读取的内容进行通信的HTTP响应。

在服务器端,如何安装模块(1);要求

在这里,我们将使用require函数来导入模块。这里我们将导入config模块。

...
const config = require('./config');
...

请创建一个名为”config.js”的新文件,并在一个名为”exports”的对象中设置值。

exports.port = 3000;

server.js如下所示。

const http   = require('http');
const config = require('./config');
const hostname = '127.0.0.1';

const server = http.createServer((req, res) => {
  res.statusCode = 200;                         // HTTPステータスコード(1)
  res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
  res.write('<html><body><strong>Hello world</strong></body></html>')
  res.end('');
});

server.listen(config.port, hostname, () => {
  console.log(`Server running at http://${hostname}:${config.port}/`);
});

(2) 当访问文件系统时,请使用fs模块进行异步访问,常常会遇到错误。

const http   = require('http');
const fs     = require('fs');
const config = require('./config');
const hostname = '127.0.0.1';

const server = http.createServer((req, res) => {
   fs.readFile(__dirname + '/server.js', 'utf-8', function (err, text) {
        // エラー発生時
        if (err) {
            res.writeHead(404, {'Content-Type' : 'text/plain'});
            res.write('page not found');
            // returnでreadFile関数を抜ける
            return res.end();
        }

        res.statusCode = 200;                         // HTTPステータスコード(1)
        res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
        res.write(text);
  });
  res.end('');
});

server.listen(config.port, hostname, () => {
  console.log(`Server running at http://${hostname}:${config.port}/`);
});

在VSCode上,出现了NodeError: Cannot set headers after they are sent to the client的错误。以下给出正确的解决方法。

const http   = require('http');
const fs     = require('fs');
const config = require('./config');
const hostname = '127.0.0.1';

const server = http.createServer((req, res) => {
   fs.readFile(__dirname + '/server.js', 'utf-8', function (err, text) {
        // エラー発生時
        if (err) {
            res.writeHead(404, {'Content-Type' : 'text/plain'});
            res.write('page not found');
            // returnでreadFile関数を抜ける
            return res.end();
        }

        res.statusCode = 200;                         // HTTPステータスコード(1)
        res.setHeader('Content-Type', 'text/plain');  // MIME-type(2)
        res.write(text);
        res.end('');
  });
  // res.end(''); 間違い
});

server.listen(config.port, hostname, () => {
  console.log(`Server running at http://${hostname}:${config.port}/`);
});

总结(课程一小时)

    • 生粋のwindowsプログラマ向けにJavascriptでWebサーバ実装

nodejs/VSCodeをインストール
ポートlisten
サーバサイドデバッグ
クライアントサイドデバッグ

改修実習では、自力でnodejsサーバプログラムをアイデアを出して改修可能になった

MIME-type: text/plain
MIME-type: text/html
HTTPヘッダContent-TypeとHTTPボディの関係
レスポンス通信は直ちに発生するわけではない
サーバサイドでのモジュール組込方法(1); require
ファイルシステムへのアクセス(非同期)

次回の内容はHTTP/GET, POSTでのパラメータ解析です
発展的な話題; そのうちやります

Content-Typeに指定するMIME-typeが他にどんなものがあるか
HTTPステータスコードの意味を押さえよう
nodejsプログラムでのモジュール組込を押さえよう
nodejsプログラムを保存したら自動でプロセス再起動してもらいたいんだけど…
VSCode/launch.jsonで何ができるの?
クライアントサイドのデバッグもVSCodeでやりたいんだけど…

参考信息

    node.js 超入門②webサーバを作る(ルーティングもやってみる)
广告
将在 10 秒后关闭
bannerAds