From 03a94ecca7409a2bb8263edf1931dbc265d0bc7c Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 29 Jan 2014 21:49:50 +0900 Subject: [PATCH] Update tutorial --- doc/tutorial-client.rst | 42 ++++-------------- doc/tutorial-server.rst | 96 +++++++++++++++-------------------------- 2 files changed, 44 insertions(+), 94 deletions(-) diff --git a/doc/tutorial-client.rst b/doc/tutorial-client.rst index bd7aae85..2c12f943 100644 --- a/doc/tutorial-client.rst +++ b/doc/tutorial-client.rst @@ -164,7 +164,7 @@ finished successfully. We first initialize nghttp2 session object in callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_header_callback = on_header_callback; - callbacks.on_end_headers_callback = on_end_headers_callback; + callbacks.on_begin_headers_callback = on_begin_headers_callback; nghttp2_session_client_new(&session_data->session, &callbacks, session_data); } @@ -386,30 +386,6 @@ multiple streams, and *stream_user_data* is very handy to identify which HEADERS we are seeing in the callback. Therefore we just show how to use it here. -The ``on_frame_recv_callback()`` function is invoked when a frame is -received from the remote peer:: - - static int on_frame_recv_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) - { - http2_session_data *session_data = (http2_session_data*)user_data; - switch(frame->hd.type) { - case NGHTTP2_HEADERS: - if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE && - session_data->stream_data->stream_id == frame->hd.stream_id) { - fprintf(stderr, "Response headers for stream ID=%d:\n", - frame->hd.stream_id); - } - break; - } - return 0; - } - -In this tutorial, we are just interested in the HTTP response -HEADERS. We check te frame type and its category (it should be -:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check -its stream ID. - Each request header name/value pair is emitted via ``on_header_callback`` function:: @@ -435,27 +411,27 @@ Each request header name/value pair is emitted via In this turotial, we just print the name/value pair. After all name/value pairs are emitted for a frame, -``on_end_headers_callback`` function is called:: +``on_frame_recv_callback`` function is called:: - static int on_end_headers_callback(nghttp2_session *session, - const nghttp2_frame *frame, - nghttp2_error_code error_code, - void *user_data) + static int on_frame_recv_callback(nghttp2_session *session, + const nghttp2_frame *frame, void *user_data) { http2_session_data *session_data = (http2_session_data*)user_data; switch(frame->hd.type) { case NGHTTP2_HEADERS: if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE && session_data->stream_data->stream_id == frame->hd.stream_id) { - fprintf(stderr, "All headers received with error_code=%d\n", error_code); + fprintf(stderr, "All headers received\n"); } break; } return 0; } -This callback may be called prematurely because of errors (e.g., -header decompression failure) which is indicated by ``error_code``. +In this tutorial, we are just interested in the HTTP response +HEADERS. We check te frame type and its category (it should be +:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check +its stream ID. The ``on_data_chunk_recv_callback()`` function is invoked when a chunk of data is received from the remote peer:: diff --git a/doc/tutorial-server.rst b/doc/tutorial-server.rst index 69a5b3ab..ff5e0552 100644 --- a/doc/tutorial-server.rst +++ b/doc/tutorial-server.rst @@ -241,9 +241,9 @@ We initialize nghttp2 session object which is done in callbacks.send_callback = send_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback; - callbacks.on_request_recv_callback = on_request_recv_callback; callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_header_callback = on_header_callback; + callbacks.on_begin_headers_callback = on_begin_headers_callback; nghttp2_session_server_new(&session_data->session, &callbacks, session_data); } @@ -414,26 +414,23 @@ We have already described about nghttp2 callback ``send_callback()``. Let's describe remaining nghttp2 callbacks we setup in ``initialize_nghttp2_setup()`` function. -The ``on_frame_recv_callback()`` function is invoked when a frame is -received from the remote peer:: +The ``on_begin_headers_callback()`` function is invoked when reception +of header block in HEADERS or PUSH_PROMISE frame is started:: - static int on_frame_recv_callback(nghttp2_session *session, - const nghttp2_frame *frame, void *user_data) + static int on_begin_headers_callback(nghttp2_session *session, + const nghttp2_frame *frame, + void *user_data) { http2_session_data *session_data = (http2_session_data*)user_data; http2_stream_data *stream_data; - switch(frame->hd.type) { - case NGHTTP2_HEADERS: - if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - break; - } - stream_data = create_http2_stream_data(session_data, frame->hd.stream_id); - nghttp2_session_set_stream_user_data(session, frame->hd.stream_id, - stream_data); - break; - default: - break; + + if(frame->hd.type != NGHTTP2_HEADERS || + frame->headers.cat != NGHTTP2_HCAT_REQUEST) { + return 0; } + stream_data = create_http2_stream_data(session_data, frame->hd.stream_id); + nghttp2_session_set_stream_user_data(session, frame->hd.stream_id, + stream_data); return 0; } @@ -448,7 +445,7 @@ order to get the object without searching through doubly linked list. In this example server, we want to serve files relative to the current working directory the program was invoked. Each header name/value pair is emitted via ``on_header_callback`` function, which is called after -``on_frame_recv_callback()``:: +``on_begin_headers_callback()``:: static int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, @@ -483,60 +480,37 @@ requested path in ``http2_stream_data`` object. In this example program, we ignore ``:method`` header field and always treat the request as GET request. -It is ok for the server to start sending response in this callback (or -in `nghttp2_on_end_headers_callback()`, which is not used in this -tutorial). In this example, we defer it to -``on_request_recv_callback()`` function. +The ``on_frame_recv_callback()`` function is invoked when a frame is +fully received:: -The ``on_request_recv_callback()`` function is invoked when all HTTP -request, including entity body, was received:: - - static int on_request_recv_callback(nghttp2_session *session, - int32_t stream_id, void *user_data) + static int on_frame_recv_callback(nghttp2_session *session, + const nghttp2_frame *frame, void *user_data) { - int fd; http2_session_data *session_data = (http2_session_data*)user_data; http2_stream_data *stream_data; - nghttp2_nv hdrs[] = { - MAKE_NV(":status", "200") - }; - char *rel_path; - - stream_data = (http2_stream_data*)nghttp2_session_get_stream_user_data - (session, stream_id); - if(!stream_data->request_path) { - if(error_reply(session, stream_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; + switch(frame->hd.type) { + case NGHTTP2_DATA: + case NGHTTP2_HEADERS: + /* Check that the client request has finished */ + if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + stream_data = nghttp2_session_get_stream_user_data(session, + frame->hd.stream_id); + /* For DATA and HEADERS frame, this callback may be called after + on_stream_close_callback. Check that stream still alive. */ + if(!stream_data) { + return 0; + } + return on_request_recv(session, session_data, stream_data); } - return 0; - } - fprintf(stderr, "%s GET %s\n", session_data->client_addr, - stream_data->request_path); - if(!check_path(stream_data->request_path)) { - if(error_reply(session, stream_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path); - fd = open(rel_path, O_RDONLY); - if(fd == -1) { - if(error_reply(session, stream_data) != 0) { - return NGHTTP2_ERR_CALLBACK_FAILURE; - } - return 0; - } - stream_data->fd = fd; - - if(send_response(session, stream_id, hdrs, ARRLEN(hdrs), fd) != 0) { - close(fd); - return NGHTTP2_ERR_CALLBACK_FAILURE; + break; + default: + break; } return 0; } First we retrieve ``http2_stream_data`` object associated to the -stream in ``on_frame_recv_callback()``. It is done using +stream in ``on_begin_headers_callback()``. It is done using `nghttp2_session_get_stream_user_data()`. If the requested path cannot be served for some reasons (e.g., file is not found), we send 404 response, which is done in ``error_reply()``. Otherwise, we open