Update tutorial
This commit is contained in:
parent
652228a9d2
commit
03a94ecca7
|
@ -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::
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue