Node.js HTTP/HTTPS 服务器和客户端的编码模式
这是一个没有使用Node.js的Express框架,用来记录HTTP/HTTPS服务器与对应客户端编码模式的备忘录。
简易版HTTP服务器
以下是一个用于返回“Hello world”的HTTP服务器的Node.js代码。下面的代码会注册一个当请求发生时的事件处理程序,并且无论何时这个HTTP服务器发生事件,都会无条件地返回“Hello world”。
var http = require('http');
// Webサーバーの作成
var server = http.createServer();
// イベントハンドラを登録する
server.on('request',function(req,res) {
res.writeHead(200,{'Content-Type': 'text/plain'});
res.write('Hello world\n');
res.end();
})
// イベントの待機
server.listen(3000);
源代码:h100_http_server.js
使用curl命令执行的结果。
这是一个使用curl命令的情况下的GET请求。
$ curl -X GET http://192.155.208.116:3000/
Hello world
如果请求方式为GET,并且附加了参数、文件夹或文件等内容,需要在服务器端进行处理以接收。
$ curl -X GET http://192.155.208.116:3000/function?query=10
Hello world
即使是在发帖的情况下也是一样的。
$ curl -X POST http://192.155.208.116:3000/function?query=10
Hello world
服务器端请求的显示
要在服务器端显示方法、文件夹和参数,需要向事件处理程序注册的回调函数中添加以下代码。
server.on('request',function(req,res) {
// リクエストの表示
console.log("Method = ", req.method);
console.log("URL = ", req.url);
显示回调函数的内容。
在进入监听器的事件等待之前,您可以执行以下代码来列出已注册的回调函数的内容。
x = server.listeners('request');
console.log(x[0].toString());
在HTTP服务器上接收数据.
接下来是接收来自客户端发送的数据的模式。在此之前,我们将创建HTTP客户端的代码。
以本地方式用中文进行改述:开发HTTP客户端以发送JSON数据。
以下是从HTTP客户端发送GET请求以传输JSON数据的代码。
var http = require("http");
var querystring = require("querystring");
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
// 送信データ作成
var json_data = {
message: 'Hello World! こんにちは',
sound: 123
}
var qs_data = querystring.stringify(json_data);
var options = {
hostname: '192.155.208.116',
port: 3000,
path: '/rest',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(qs_data)
}
};
// リクエスト定義と応答処理設定
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);
// Query String -> JSON形式へ変換
var rcv_text = querystring.parse(decoder.write(chunk))
var rcv_json_text = JSON.stringify(rcv_text);
var rcv_json = JSON.parse(rcv_json_text);
console.log("json text = ", rcv_json.message);
console.log("json number = ", rcv_json.sound);
console.log("json boolean = ", rcv_json.reply);
});
// 応答終了処理
res.on('end', function(){
console.log('これ以上データはありません。')
});
});
// 送信のエラー処理
req.on('error', function(e){
console.log( "エラー発生: ", e.message);
});
// データ送信(GET)
req.write(qs_data);
req.end();
源代码:
h201_http_get.js
这是加载所需模块的数据传输部分。它将转换为可以附加到HTTP请求的查询字符串,并设置接收响应消息时的解码字符编码。
var querystring = require("querystring");
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
将 JSON 格式的数据 json_data 转换为查询字符串形式,以便向服务器发送。然后,将包含发送目标和内容定义数据的选项设置为options,并在创建请求时使用。
var json_data = {
message: 'Hello World! こんにちは',
sound: 123
}
var qs_data = querystring.stringify(json_data);
var options = {
hostname: '192.155.208.116',
port: 3000,
path: '/rest',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(qs_data)
}
};
以下的代码定义了向服务器发送请求和处理服务器响应的回调函数。这段代码并不实际发送请求。
var req = http.request(options, function(res) {
console.log("STATUS: ", res.statusCode);
console.log("HEADERS: ", JSON.stringify(res.headers));
// 応答受信処理
res.on('data', function(chunk){
console.log("BODY: ", chunk);
// Query String -> JSON形式へ変換
var rcv_text = querystring.parse(decoder.write(chunk))
var rcv_json_text = JSON.stringify(rcv_text);
var rcv_json = JSON.parse(rcv_json_text);
console.log("json text = ", rcv_json.message);
console.log("json number = ", rcv_json.sound);
console.log("json boolean = ", rcv_json.reply);
});
// 応答終了処理
res.on('end', function(){
console.log('これ以上データはありません。')
});
});
以下的代碼是一個在從客戶端發送到服務器時發生錯誤時進行回調的函數。
req.on('error', function(e){
console.log( "エラー発生: ", e.message);
});
举个例子,如果服务器停止工作,将会显示以下消息。
$ ./h201_http_get.js
エラー発生: connect ECONNREFUSED
以下是用于发送先前设置的请求的代码。一旦执行此代码,请求将被发送出去。
// データ送信(GET)
req.write(qs_data);
req.end();
源代码:h201_http_get.js
使用POST方法发送请求的客户端
要发送POST请求,需要将options的方法更改为POST。顺便也要更改变量名。
var post_data = querystring.stringify(json_data);
var options = {
hostname: '192.155.208.116',
port: 3000,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(post_data)
}
};
为了使代码易读,我也会将变量名更改。
// データ送信(POST)
req.write(post_data);
req.end();
源代码: h200_http_post.js
开发接收HTTP服务器发送数据的代码
下一步是开发服务器端,因为我们已经有了客户端。我们将在低级别的HTTP服务器代码中添加一个模块,用于将接收到的数据转换成JSON格式。
var querystring = require("querystring");
const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8');
另外,在回调函数中,我们将添加代码将查询字符串转换为JSON格式的变量并进行存储。同时,我们会对接收到的数据添加信息并进行回复。
server.on('request',function(req,res) {
// リクエストの表示
console.log("Method = ", req.method);
console.log("URL = ", req.url);
// POSTデータ受信処理
req.on('data',function(chunk) {
console.log("header = ", req.headers);
// Query String -> JSON形式へ変換
var rcv_data = querystring.parse(decoder.write(chunk))
var rcv_text = JSON.stringify(rcv_data);
var rcv_json = JSON.parse(rcv_text);
console.log("json text = ", rcv_json.message);
console.log("json number = ", rcv_json.sound);
console.log("json boolean = ", rcv_json.reply);
// 何かの処理
rcv_json.message = "こんにちは、良い天気ですね。";
rcv_json.reply = true;
// 応答送信
res.writeHead(200,{'Content-Type': 'application/json'});
var text_data = JSON.stringify(rcv_json);
var ReplyData = querystring.stringify(rcv_json);
res.write(ReplyData);
res.end();
});
});
源代码:h102_http_server2.js
如果是服务器端的GET请求,则返回执行结果。
Method = GET
URL = /rest
header = { 'content-type': 'application/json',
'content-length': '80',
host: '192.155.208.116:3000',
connection: 'close' }
json text = Hello World! こんにちは
json number = 123
json boolean = undefined
当执行服务器端的POST请求时,结果如下。
Method = POST
URL = /upload
header = { 'content-type': 'application/x-www-form-urlencoded',
'content-length': '80',
host: '192.155.208.116:3000',
connection: 'close' }
json text = Hello World! こんにちは
json number = 123
json boolean = undefined
低水平的HTTPS服务器
下一步,我们将对低级别的HTTP服务器代码进行升级,变成HTTPS服务器。
域名
要创建HTTPS服务器,您需要为服务器的IP地址获取DNS名称和证书。如果想免费获取域名,可以使用MyDNS方便地进行办理。
证书
您可以使用Let’s Encrypt来获取免费的证书。您需使用先前创建的域名来生成证书。
添加的代码部分 de
使用JSON格式读取key和cert,然后将其设置给创建HTTPS服务器的函数。这样,HTTPS服务器的升级就完成了。
var fs = require('fs');
var https = require('https');
中略
var options = {
key: fs.readFileSync('../lets_encript.key'),
cert: fs.readFileSync('../lets_encript_fullchain.crt')
};
server = https.createServer(options);
源代码:h101_https_server.js
运行curl命令的结果.
当使用IP地址访问时,会出现以下错误。
$ curl -X GET https://192.155.208.116:3000/
curl: (51) SSL: certificate subject name 'www.mahotakara.wjg.jp' does not match target host name '192.155.208.116'
这是通过DNS名称使用GET方法访问的结果。
$ curl -X GET https://www.mahotakara.wjg.jp:3000/
Hello world
以下是使用POST方法访问的结果:
~~~
$ curl -X POST https://www.mahotakara.wjg.jp:3000/
你好,世界!
~~~
在HTTPS服务器上接收数据
在低级别的HTTPS服务器上,我们添加了一些代码。添加代码的方式和HTTP服务器的情况相同。
源代码:h103_https_server2.js
HTTPS客户端的开发
追加的内容与HTTP客户端相同。
这是GET的源代码。 h203_https_get.js 但是,如果需要保密性,则不应使用GET。原因是,请参考IPA的网络文章“通过查询字符串泄露信息”。
以下是适用于生产环境推荐的POST案例的源代码h202_https_post.js。
发帖执行结果。
客户端控制台和日志输出
$ ./h202_https_post.js
STATUS: 200
HEADERS: {"content-type":"application/json","date":"Sun, 07 May 2017 07:21:46 GMT","connection":"close","transfer-encoding":"chunked"}
BODY: message=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%E3%80%81%E8%89%AF%E3%81%84%E5%A4%A9%E6%B0%97%E3%81%A7%E3%81%99%E3%81%AD%E3%80%82&sound=123&reply=true
json text = こんにちは、良い天気ですね。
json number = 123
json boolean = true
これ以上データはありません。
服务器端控制台和日志输出
Method = POST
URL = /upload
header = { 'content-type': 'application/x-www-form-urlencoded',
'content-length': '80',
host: 'www.mahotakara.wjg.jp:3000',
connection: 'close' }
json text = Hello World! こんにちは
json number = 123
json boolean = undefined
请查阅参考资料。
-
- Node.js v4.8.3 Documentation HTTP
-
- Node.js v4.8.3 Documentation HTTPS
-
- Node.js v4.8.3 Documentation Query String
- MDN JavaScript Object Notation