发送 HTTP/2 POST 请求 NodeJS
Sending HTTP/2 POST request NodeJS
我正在尝试弄清楚如何使用 NodeJS 发送 HTTP/2 POST 请求。我与文档中的示例相去甚远:
const http2 = require('http2');
const fs = require('fs');
const client = http2.connect('https://localhost:8443', {
ca: fs.readFileSync('localhost-cert.pem')
});
client.on('error', (err) => console.error(err));
client.on('socketError', (err) => console.error(err));
const req = client.request({ ':path': '/' });
req.on('response', (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}
});
req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => {
console.log(`\n${data}`);
client.close();
});
req.end();
但我不清楚如何实际设置数据以 POST.
发送
在拼凑了各处的小信息后,我终于设法解决了这个问题。这是一个模板示例。关键在req.write()。老实说,我无法在任何地方找到有关如何包含 body 的直接答案。几乎每个示例都没有 body!希望这对其他人有帮助。注意:这是在 Node-red 中,因此是 global.get 语句,但也可以通过将它们更改为 require('module'):
const fs = global.get('fs');
const http2 = global.get('http2');
fs.readFile('turn-off-the-desklight.raw', function(err, content){
if(err){
node.send(err);
}
var metadata = JSON.stringify(
{
"context": [
{
"header": {
"namespace": "SpeechRecognizer",
"name": "RecognizerState"
},
"payload": {
}
},
{
"header": {
"namespace": "Speaker",
"name": "VolumeState"
},
"payload": {
"volume": 10,
"muted": false
}
},
{
"header": {
"namespace": "Alerts",
"name": "AlertsState"
},
"payload": {
"allAlerts": [],
"activeAlerts": []
}
},
{
"header": {
"namespace": "SpeechSynthesizer",
"name": "SpeechState"
},
"payload": {
"token": "",
"offsetInMilliseconds": 0,
"playerActivity": "FINISHED"
}
},
{
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackState"
},
"payload": {
"token": "",
"offsetInMilliseconds": 0,
"playerActivity": "IDLE"
}
}
],
"event": {
"header": {
"namespace": "SpeechRecognizer",
"name": "Recognize",
"messageId": "1eff3c5e-02e3-4dd3-9ca0-7c38937f005f",
"dialogRequestId": "a905c2bb-1bbd-45cf-9f85-6563d2546492"
},
"payload": {
"profile": "FAR_FIELD",
"format": "AUDIO_L16_RATE_16000_CHANNELS_1"
}
}
});
var data = "--this-is-my-boundary-for-alexa\r\n";
data += 'Content-Disposition: form-data; name="metadata"\r\n';
data +='Content-Type: application/json; charset=UTF-8\r\n\r\n';
data += metadata;
data += "\r\n";
data += "--this-is-my-boundary-for-alexa\r\n";
data += "Content-Disposition: form-data; name=\"audio\"\r\n";
data += "Content-Type:application/octet-stream\r\n\r\n";
var payload = Buffer.concat([
Buffer.from(data, "utf8"),
new Buffer(content, 'binary'),
Buffer.from("\r\n--this-is-my-boundary-for-alexa\r\n", "utf8"),
]);
const client = global.get('alexaClient');
client.on('error', (err) => node.send({payload:err}));
client.on('socketError', (err) => node.send({payload:err}));
var request = {
':method' : 'POST',
':scheme' : 'https',
':path' : '/v20160207/events',
'authorization' : 'Bearer <valid token>',
'content-type' : 'multipart/form-data; boundary=this-is-my-boundary-for-alexa'
};
var req = client.request(request);
req.on('response', (headers, flags) => {
for (const name in headers) {
if(name === ':status') {
node.send({payload:`${name}: ${headers[name]}`});
}
}
});
req.on('error', function(err) {
node.send(err);
});
req.setEncoding('utf8');
let outdata = '';
req.on('data', (chunk) => { outdata += chunk; });
req.on('end', () => {
node.send({payload:outdata});
});
req.write(payload);
req.end();
});
如果您需要 post 您的对象作为 json - 您应该将其字符串化并包装在缓冲区中。这是适用于我的情况的代码:
const http2 = require('http2');
const post = (url, path, body) => new Promise((resolve) => {
const client = http2.connect(url);
const buffer = Buffer.from(JSON.stringify(body));
const req = client.request({
[http2.constants.HTTP2_HEADER_SCHEME]: "https",
[http2.constants.HTTP2_HEADER_METHOD]: http2.constants.HTTP2_METHOD_POST,
[http2.constants.HTTP2_HEADER_PATH]: `/${path}`,
"Content-Type": "application/json",
"Content-Length": buffer.length,
});
req.setEncoding('utf8');
let data = [];
req.on('data', (chunk) => {
data.push(chunk);
});
req.write(buffer);
req.end();
req.on('end', () => {
resolve({ data: data.join("") });
});
});
您可以向服务器发送数据并从服务器接收数据。
1) 客户
const http2 = require('http2');
var port = 15000;
const client = http2.connect('https://localhost:15000/');
// Must not specify the ':path' and ':scheme' headers
// for CONNECT requests or an error will be thrown.
var body = "Hello, I am babatman";
const req = client.request({
':method': 'POST',
':authority': `localhost:${port}`,
'body': body
});
req.on('response', (headers) => {
console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
});
let data = '';
req.setEncoding('utf8');
req.on('data', (chunk) => data += chunk);
req.on('end', () => {
console.log(`The server says: ${data}`);
client.close();
});
2) 服务器
app.use(async ctx => {
console.log(ctx.request);
ctx.response.status = 201;
ctx.body = "hello";
console.log("Response 201 was send.")
});
我正在尝试弄清楚如何使用 NodeJS 发送 HTTP/2 POST 请求。我与文档中的示例相去甚远:
const http2 = require('http2');
const fs = require('fs');
const client = http2.connect('https://localhost:8443', {
ca: fs.readFileSync('localhost-cert.pem')
});
client.on('error', (err) => console.error(err));
client.on('socketError', (err) => console.error(err));
const req = client.request({ ':path': '/' });
req.on('response', (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}
});
req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => {
console.log(`\n${data}`);
client.close();
});
req.end();
但我不清楚如何实际设置数据以 POST.
发送在拼凑了各处的小信息后,我终于设法解决了这个问题。这是一个模板示例。关键在req.write()。老实说,我无法在任何地方找到有关如何包含 body 的直接答案。几乎每个示例都没有 body!希望这对其他人有帮助。注意:这是在 Node-red 中,因此是 global.get 语句,但也可以通过将它们更改为 require('module'):
const fs = global.get('fs');
const http2 = global.get('http2');
fs.readFile('turn-off-the-desklight.raw', function(err, content){
if(err){
node.send(err);
}
var metadata = JSON.stringify(
{
"context": [
{
"header": {
"namespace": "SpeechRecognizer",
"name": "RecognizerState"
},
"payload": {
}
},
{
"header": {
"namespace": "Speaker",
"name": "VolumeState"
},
"payload": {
"volume": 10,
"muted": false
}
},
{
"header": {
"namespace": "Alerts",
"name": "AlertsState"
},
"payload": {
"allAlerts": [],
"activeAlerts": []
}
},
{
"header": {
"namespace": "SpeechSynthesizer",
"name": "SpeechState"
},
"payload": {
"token": "",
"offsetInMilliseconds": 0,
"playerActivity": "FINISHED"
}
},
{
"header": {
"namespace": "AudioPlayer",
"name": "PlaybackState"
},
"payload": {
"token": "",
"offsetInMilliseconds": 0,
"playerActivity": "IDLE"
}
}
],
"event": {
"header": {
"namespace": "SpeechRecognizer",
"name": "Recognize",
"messageId": "1eff3c5e-02e3-4dd3-9ca0-7c38937f005f",
"dialogRequestId": "a905c2bb-1bbd-45cf-9f85-6563d2546492"
},
"payload": {
"profile": "FAR_FIELD",
"format": "AUDIO_L16_RATE_16000_CHANNELS_1"
}
}
});
var data = "--this-is-my-boundary-for-alexa\r\n";
data += 'Content-Disposition: form-data; name="metadata"\r\n';
data +='Content-Type: application/json; charset=UTF-8\r\n\r\n';
data += metadata;
data += "\r\n";
data += "--this-is-my-boundary-for-alexa\r\n";
data += "Content-Disposition: form-data; name=\"audio\"\r\n";
data += "Content-Type:application/octet-stream\r\n\r\n";
var payload = Buffer.concat([
Buffer.from(data, "utf8"),
new Buffer(content, 'binary'),
Buffer.from("\r\n--this-is-my-boundary-for-alexa\r\n", "utf8"),
]);
const client = global.get('alexaClient');
client.on('error', (err) => node.send({payload:err}));
client.on('socketError', (err) => node.send({payload:err}));
var request = {
':method' : 'POST',
':scheme' : 'https',
':path' : '/v20160207/events',
'authorization' : 'Bearer <valid token>',
'content-type' : 'multipart/form-data; boundary=this-is-my-boundary-for-alexa'
};
var req = client.request(request);
req.on('response', (headers, flags) => {
for (const name in headers) {
if(name === ':status') {
node.send({payload:`${name}: ${headers[name]}`});
}
}
});
req.on('error', function(err) {
node.send(err);
});
req.setEncoding('utf8');
let outdata = '';
req.on('data', (chunk) => { outdata += chunk; });
req.on('end', () => {
node.send({payload:outdata});
});
req.write(payload);
req.end();
});
如果您需要 post 您的对象作为 json - 您应该将其字符串化并包装在缓冲区中。这是适用于我的情况的代码:
const http2 = require('http2');
const post = (url, path, body) => new Promise((resolve) => {
const client = http2.connect(url);
const buffer = Buffer.from(JSON.stringify(body));
const req = client.request({
[http2.constants.HTTP2_HEADER_SCHEME]: "https",
[http2.constants.HTTP2_HEADER_METHOD]: http2.constants.HTTP2_METHOD_POST,
[http2.constants.HTTP2_HEADER_PATH]: `/${path}`,
"Content-Type": "application/json",
"Content-Length": buffer.length,
});
req.setEncoding('utf8');
let data = [];
req.on('data', (chunk) => {
data.push(chunk);
});
req.write(buffer);
req.end();
req.on('end', () => {
resolve({ data: data.join("") });
});
});
您可以向服务器发送数据并从服务器接收数据。
1) 客户
const http2 = require('http2');
var port = 15000;
const client = http2.connect('https://localhost:15000/');
// Must not specify the ':path' and ':scheme' headers
// for CONNECT requests or an error will be thrown.
var body = "Hello, I am babatman";
const req = client.request({
':method': 'POST',
':authority': `localhost:${port}`,
'body': body
});
req.on('response', (headers) => {
console.log(headers[http2.constants.HTTP2_HEADER_STATUS]);
});
let data = '';
req.setEncoding('utf8');
req.on('data', (chunk) => data += chunk);
req.on('end', () => {
console.log(`The server says: ${data}`);
client.close();
});
2) 服务器
app.use(async ctx => {
console.log(ctx.request);
ctx.response.status = 201;
ctx.body = "hello";
console.log("Response 201 was send.")
});