【问题标题】:Sending HTTP/2 POST request NodeJS发送 HTTP/2 POST 请求 NodeJS
【发布时间】:2018-07-07 14:10:59
【问题描述】:

我正在尝试弄清楚如何使用 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 发送。

【问题讨论】:

    标签: node.js post http2


    【解决方案1】:

    如果您需要将对象作为 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("") });
        });
    });
    

    【讨论】:

    • 只要我将连接更改为包含一个空字符串分隔符:data.join(""),上面的示例就适用于我。否则它最终会在结果中添加额外的逗号。
    【解决方案2】:

    在到处拼凑一点点信息之后,我终于设法解决了这个问题。这是一个模板示例。关键在 req.write() 中。老实说,我在任何地方都找不到关于如何包含身体的直接答案。几乎每个例子都没有实体!希望这对其他人有帮助。注意:这是 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();  
    }); 
    

    【讨论】:

    • 无论我做什么,在 req.write 和 req.end 之后,我都没有看到数据被发送到服务器。服务器甚至在另一端指示缓冲区为空。
    • @Nick 打开另一个问题并发布您的代码,然后链接回此处。我去看看。
    • @JohnSmith 感谢您提供的代码。您能否将音频保存到本地磁盘?我想将响应从语音转换为文本。
    【解决方案3】:

    您可以向服务器发送数据,也可以从服务器接收数据。

    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.")
    });
    

    【讨论】:

      猜你喜欢
      • 2016-03-31
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 2016-04-08
      相关资源
      最近更新 更多