nghttp2 多部分 POST 消息
nghttp2 multipart POST message
我目前正在尝试使用 nghttp2
构建多部分消息。该消息应按以下结构。
我应该使用 nghttp2_submit_request
(here) 函数,nva
作为我的 HTTP/2 header,nghttp2_data_provider *data_prd
作为我的数据。但是,我仍然不明白如何创建两条消息(两条消息 headers)。
更新:
我可以在我的源代码中描述我的想法吗?请看下面。在这里,我使用 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) 如何向音频添加 header(更具体地说是消息 header)。
2) 如何在 Json 文件后附加它。
一个multi-part mime header通常是这样定义的:
-----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
如果内容是二进制的,你会 usually encode it as base-64 有一个固定的行长度(你 也可以 发送二进制数据,但必须采取额外的预防措施 white-spaces 例如最后的 line-feed)。 header field-name 说明可以包括在内:
Content-Transfer-Encoding: Base64
(二进制数据使用值“binary”代替)。
边界 ID 必须足够唯一,以免成为任何其他内容的一部分。它在主 header 中定义时不使用 double-dashes,但你需要在它作为分隔符的任何地方添加这样的 double-dashes。
所以在这种情况下,整个消息看起来像这样:
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
我目前正在尝试使用 nghttp2
构建多部分消息。该消息应按以下结构。
我应该使用 nghttp2_submit_request
(here) 函数,nva
作为我的 HTTP/2 header,nghttp2_data_provider *data_prd
作为我的数据。但是,我仍然不明白如何创建两条消息(两条消息 headers)。
更新:
我可以在我的源代码中描述我的想法吗?请看下面。在这里,我使用 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) 如何向音频添加 header(更具体地说是消息 header)。 2) 如何在 Json 文件后附加它。
一个multi-part mime header通常是这样定义的:
-----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
如果内容是二进制的,你会 usually encode it as base-64 有一个固定的行长度(你 也可以 发送二进制数据,但必须采取额外的预防措施 white-spaces 例如最后的 line-feed)。 header field-name 说明可以包括在内:
Content-Transfer-Encoding: Base64
(二进制数据使用值“binary”代替)。
边界 ID 必须足够唯一,以免成为任何其他内容的一部分。它在主 header 中定义时不使用 double-dashes,但你需要在它作为分隔符的任何地方添加这样的 double-dashes。
所以在这种情况下,整个消息看起来像这样:
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