void onRequest (Session& session) { session.write (std::string ("Hello, world!\n")); if (is_keep_alive(session.request())) session.complete(); else session.close (true); }
void testPrepare() { request_v1<empty_body> m; m.version = 10; BEAST_EXPECT(! is_upgrade(m)); m.headers.insert("Transfer-Encoding", "chunked"); try { prepare(m); fail(); } catch(std::exception const&) { } m.headers.erase("Transfer-Encoding"); m.headers.insert("Content-Length", "0"); try { prepare(m); fail(); } catch(std::exception const&) { pass(); } m.headers.erase("Content-Length"); m.headers.insert("Connection", "keep-alive"); try { prepare(m); fail(); } catch(std::exception const&) { pass(); } m.version = 11; m.headers.erase("Connection"); m.headers.insert("Connection", "close"); BEAST_EXPECT(! is_keep_alive(m)); }
static void ev_handler(struct ns_connection *nc, int ev, void *ev_data) { struct conn_data *conn = (struct conn_data *) nc->user_data; const time_t now = time(NULL); #ifdef DEBUG write_log("%d conn=%p nc=%p ev=%d ev_data=%p bec=%p bec_nc=%p\n", now, conn, nc, ev, ev_data, conn != NULL ? conn->be_conn : NULL, conn != NULL && conn->be_conn != NULL ? conn->be_conn->nc : NULL); #endif if (conn == NULL) { if (ev == NS_ACCEPT) { conn = calloc(1, sizeof(*conn)); if (conn == NULL) { send_http_err(nc, s_error_500); } else { memset(conn, 0, sizeof(*conn)); nc->user_data = conn; conn->client.nc = nc; conn->client.body_len = -1; conn->backend.body_len = -1; conn->last_activity = now; } return; } else { nc->flags |= NSF_CLOSE_IMMEDIATELY; return; } } if (ev != NS_POLL) conn->last_activity = now; switch (ev) { case NS_HTTP_REQUEST: { /* From client */ assert(conn != NULL); assert(conn->be_conn == NULL); struct http_message *hm = (struct http_message *) ev_data; conn->client.flags.keep_alive = is_keep_alive(hm); if (!connect_backend(conn, hm)) { respond_with_error(conn, s_error_500); break; } if (conn->backend.nc == NULL) { /* This is a redirect, we're done. */ conn->client.nc->flags |= NSF_SEND_AND_CLOSE; break; } forward(conn, hm, &conn->client, &conn->backend); break; } case NS_CONNECT: { /* To backend */ assert(conn != NULL); assert(conn->be_conn != NULL); int status = *(int *) ev_data; if (status != 0) { write_log("Error connecting to %s: %d (%s)\n", conn->be_conn->be->host_port, status, strerror(status)); /* TODO(lsm): mark backend as defunct, try it later on */ respond_with_error(conn, s_error_500); conn->be_conn->nc = NULL; release_backend(conn); break; } break; } case NS_HTTP_REPLY: { /* From backend */ assert(conn != NULL); struct http_message *hm = (struct http_message *) ev_data; conn->backend.flags.keep_alive = s_backend_keepalive && is_keep_alive(hm); forward(conn, hm, &conn->backend, &conn->client); release_backend(conn); if (!conn->client.flags.keep_alive) { conn->client.nc->flags |= NSF_SEND_AND_CLOSE; } else { #ifdef DEBUG write_log("conn=%p remains open\n", conn); #endif } break; } case NS_POLL: { assert(conn != NULL); if (now - conn->last_activity > CONN_IDLE_TIMEOUT && conn->backend.nc == NULL /* not waiting for backend */) { #ifdef DEBUG write_log("conn=%p has been idle for too long\n", conn); conn->client.nc->flags |= NSF_SEND_AND_CLOSE; #endif } break; } case NS_CLOSE: { assert(conn != NULL); if (nc == conn->client.nc) { #ifdef DEBUG write_log("conn=%p nc=%p client closed, body_sent=%d\n", conn, nc, conn->backend.body_sent); #endif conn->client.nc = NULL; if (conn->backend.nc != NULL) { conn->backend.nc->flags |= NSF_CLOSE_IMMEDIATELY; } } else if (nc == conn->backend.nc) { #ifdef DEBUG write_log("conn=%p nc=%p backend closed\n", conn, nc); #endif conn->backend.nc = NULL; if (conn->client.nc != NULL && (conn->backend.body_len < 0 || conn->backend.body_sent < conn->backend.body_len)) { write_log("Backend %s disconnected.\n", conn->be_conn->be->host_port); respond_with_error(conn, s_error_500); } } if (conn->client.nc == NULL && conn->backend.nc == NULL) { free(conn); } break; } } }