【问题标题】:nghttp2 multipart POST messagenghttp2 多部分 POST 消息
【发布时间】:2017-12-22 13:57:42
【问题描述】:

我目前正在尝试使用nghttp2 来构建多部分消息。消息的结构应如下所示。

我应该使用nghttp2_submit_request(here) 函数,nva 作为我的 HTTP/2 标头,nghttp2_data_provider *data_prd 作为我的数据。但是,我仍然不明白如何准确地创建两条消息(带有两个消息头)。


更新:

我可以在源代码中描述我的想法吗?请看下文。在这里,我使用nghttp2_data_provider 打开一个音频文件,并写入缓冲区。

ssize_t data_prd_read_callback(
    nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length,
    uint32_t *data_flags, nghttp2_data_source *source, void *user_data) 
{

  printf("[INFO] C ----------------------------> S (DATA post body), length:%zu\n", length);

  int fd = source->fd;
  ssize_t r;
// writting my opened audio file into buffer
  while ((r = read(fd, buf, length)) == -1 && errno == EINTR); 
  printf("stream_id:%d, nread:%zu\r\n", stream_id, r);
  return nread;
}



void submit_postAudio(http2_session_data *session_data) {
  int32_t stream_id;
  http2_stream_data *stream_data = session_data->stream_data[STREAM_ID_REQUESTAUDIO];
  const char *uri = stream_data->uri;
  const struct http_parser_url *u = stream_data->u;
  char byLength = 0;

  const nghttp2_nv hdrs[] = {
  MAKE_NV(":method", "POST"),   MAKE_NV_CS(":path", stream_data->path),
  MAKE_NV(":scheme", "https"), MAKE_NV("accept", "*/*"),    
  MAKE_NV_CS("authorization", stream_data->access_token),
  MAKE_NV("content-type", "multipart/form-data; boundary=abcdefg123")
  };

  fprintf(stderr, "Request headers:\n");
  print_headers(stderr, hdrs, ARRLEN(hdrs));

  int fileDescriptor = open ("/my_audio.wmv", O_APPEND);  // open my audio file 
  nghttp2_data_provider data_prd;
  data_prd.source.fd = fileDescriptor   // set the file descriptor 
  data_prd.source.ptr = NULL;
  data_prd.read_callback = data_prd_read_callback;

  stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
                                     ARRLEN(hdrs), &data_prd, stream_data);
  if (stream_id < 0) {
    errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
  }

  stream_data->stream_id = stream_id;
}

让我困惑的是 1)如何向音频添加标题(更具体的消息标题)。 2)如何在我的 Json 文件之后附加它。

【问题讨论】:

    标签: http2 alexa avspeechsynthesizer nghttp2


    【解决方案1】:

    多部分 mime 标头通常定义如下:

    -----boundary_id
    name: value  # header stuff here, ie. "name: value" per line. No spaces in name, all ASCII
    CRLF         # End of header is defined with an extra linefeed, AKA a "null line", see ref 1.
    
    content here, ends at next boundary id
    
    -----boundary_id
    

    Ref 1

    如果内容是二进制的,您将usually encode it as base-64 使用固定的行长度(您可以也发送二进制数据,但必须注意额外的空格,例如最后的换行符)。可以包含说明这一点的标题字段名称:

    Content-Transfer-Encoding: Base64
    

    (对于二进制数据,使用值“binary”代替)。

    边界 ID 必须足够独特,以免成为任何其他内容的一部分。它在主标题中定义时不使用双破折号,但您需要在它作为分隔符的任何地方添加这样的双破折号。

    所以在这种情况下,整个消息看起来像这样:

    name1: value1
    name2: value2
    name3: value3
    x-comment: "as required by the specs (ignore this line)"
    content-type: multipart/form-data; boundary: my_unique_boundary_id
    
    --my_unique_boundary_id
    Content-Disposition: form-data; name="metadata"
    Content-Type: application/json; charset=UTF-08
    
    {JSON data here}
    
    --my_unique_boundary_id
    Content-Disposition: form-data; name="audio"
    Content-Type: application/octet-stream
    Content-Transfer-Encoding: Base64
    x-comment: "binary audio encoded as base-64 follows next"
    
    UklGRuKlAABXQVZFZm10ICgAAAABAAEARKwAAIhYAQACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAc2NvdLQBAAAAAAAAVGhlIFJoeXRobSBNYWNoaW5lICAgICAgICAgICAgICAgICAgICAgICAg
    IFRSTTEAICA6MDAAAAAAAAAvADAwMDAwMDAwMDAwMAAAALkBTQABAAAAJQAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABKYXNvbiBE
    b25uZWxseSAoYWthIGRqIHB1enpsZSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
    ICAgIDAwQwAAAAAAADEyMTMwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    ... etc.
    
    --my_unique_boundary_id
    

    【讨论】:

    • 在最后一个 MIME 部分中将标题与正文分开需要空行。
    • @Alex ups,我在删除 CRLF 表示时不小心删除了
    • 感谢您的回答。从ssize_t data_prd_read_callback( nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) ,我只有一个缓冲区(uint8_t *)来写入我的有效负载。您是否建议以这种格式简单地编写 char (具有正确的间距和换行符),然后跟随音频文件?
    • @wrek 我不熟悉有问题的 API,但总的来说,是的,多部分基本上是一个长文本字符串。它可以直接复制到字节缓冲区(如果涉及 unicode,请注意字节顺序;不过在这里应该不是问题)。通常这一步不是必需的,因为多部分的目的是使其可以作为字符串自行传输,但如果 api 需要一个字节缓冲区也应该工作,音频数据将已经包含在字符串为 base-64(您需要首先将音频数据转换为。如果选择此方法,则为原始二进制文件)。
    • @k3n,还有一个问题,在音频文件的末尾,你知道我是简单地包含一个新行还是应该以 NULL 结尾?
    猜你喜欢
    • 1970-01-01
    • 2016-03-04
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 2014-04-21
    • 2013-05-05
    相关资源
    最近更新 更多