2017-07-17 2 views
7

J'essaie actuellement d'utiliser nghttp2 pour créer un message en plusieurs parties. Le message doit être strcuture comme suit.nghttp2 multipart POST message

enter image description here

je devrais utiliser la fonction nghttp2_submit_request(here), avec nva comme mon en-tête HTTP/2, et nghttp2_data_provider *data_prd pour mes données. Cependant, je ne comprends toujours pas exactement comment je peux créer deux messages (avec deux en-têtes de message).


Mise à jour:

moi Est-il possible de décrire ce que je pense dans mon code source? S'il vous plaît voir ci-dessous. Ici, j'utilise nghttp2_data_provider pour ouvrir un fichier audio et écrire dans le tampon.

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; 
} 

Ce qui me confondre est 1) comment puis-je ajouter un en-tête (un en-tête de message pour être plus précis) à l'audio. 2) comment l'ajouter après mon fichier Json.

Répondre

0

Un en-tête MIME en plusieurs parties est généralement définie comme ceci:

-----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

Si le contenu est binaire vous usually encode it as base-64 avec une longueur de ligne fixe (vous pouvez envoyer des données binaires trop mais doivent prendre des précautions quant aux espaces blancs supplémentaires tels qu'un dernier saut de ligne). Un en-tête champ nom indiquant ce qui peut être inclus:

Content-Transfer-Encoding: Base64 

(pour la valeur de l'utilisation des données binaires « binaire » au lieu).

L'ID de limite doit être suffisamment unique pour ne pas risquer de faire partie d'un autre contenu. Il n'utilise pas de doubles tirets lorsqu'il est défini dans l'en-tête principal, mais vous devez le préfixer avec de tels doubles tirets partout où il agit comme un séparateur.

Donc, dans ce cas, le message entier ressemblerait à quelque chose comme ceci:

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 
+0

ligne vide nécessaire pour séparer l'en-tête du corps dans la dernière partie MIME. – Alex

+0

@Alex ups, j'ai accidentellement supprimé lors de la suppression d'une représentation CRLF – K3N

+0

Merci pour votre réponse. De la 'ssize_t data_prd_read_callback ( session nghttp2_session *, int32_t flux_id, uint8_t * buf, longueur size_t, uint32_t * data_flags, nghttp2_data_source * source, void * données_utilisateur)', j'ai seulement un tampon ('uint8_t *') pour écrire mon charge utile à. Suggérez-vous d'écrire simplement char dans ce format (avec l'espacement correct et la nouvelle ligne), puis suivez le fichier audio? – wrek