http-server-request.c revision a5886aec87fbfd767a110e6168ce96411acfe798
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic inline void
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_debug(struct http_server_request *req,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic inline void
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenhttp_server_request_debug(struct http_server_request *req,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen const char *format, ...)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic inline void
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_error(struct http_server_request *req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic inline void
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_error(struct http_server_request *req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen const char *format, ...)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic inline void
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_client_error(struct http_server_request *req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic inline void
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenhttp_server_request_client_error(struct http_server_request *req,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen const char *format, ...)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenhttp_server_request_new(struct http_server_connection *conn)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen static unsigned int id_counter = 0;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"http_server_request", 4096);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen req = p_new(pool, struct http_server_request, 1);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen http_server_connection_add_request(conn, req);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenvoid http_server_request_ref(struct http_server_request *req)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenbool http_server_request_unref(struct http_server_request **_req)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct http_server_connection *conn = req->conn;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen http_server_connection_remove_request(conn, req);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid http_server_request_connection_close(struct http_server_request *req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid http_server_request_destroy(struct http_server_request **_req)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* just make sure the request ends in a proper state */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen void (*callback)(void *) = req->destroy_callback;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen#undef http_server_request_set_destroy_callback
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenvoid http_server_request_set_destroy_callback(struct http_server_request *req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen void (*callback)(void *),
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenvoid http_server_request_abort(struct http_server_request **_req,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct http_server_connection *conn = req->conn;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (req->state >= HTTP_SERVER_REQUEST_STATE_FINISHED)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_connection_remove_request(conn, req);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* send best-effort response if appropriate */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state >= HTTP_SERVER_REQUEST_STATE_PROCESSING &&
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen static const char *response =
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen "HTTP/1.1 500 Internal Server Error\r\n"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen "Content-Length: 0\r\n"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* close the connection */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state = HTTP_SERVER_REQUEST_STATE_ABORTED;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_get(struct http_server_request *req)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_get_pool(struct http_server_request *req)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenhttp_server_request_get_response(struct http_server_request *req)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenint http_server_request_get_auth(struct http_server_request *req,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen auth = http_request_header_get(&req->req, "Authorization");
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ((const unsigned char *)auth, strlen(auth), credentials) < 0)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenbool http_server_request_is_finished(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state == HTTP_SERVER_REQUEST_STATE_ABORTED;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenbool http_server_request_is_complete(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return (req->failed || req->conn->input_broken ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen (req->next != NULL && !http_server_request_is_new(req->next)) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen !http_server_connection_pending_payload(req->conn));
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid http_server_request_halt_payload(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid http_server_request_continue_payload(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen i_assert(req->state <= HTTP_SERVER_REQUEST_STATE_QUEUED);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (req->req.expect_100_continue && !req->sent_100_continue)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_connection_trigger_responses(req->conn);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid http_server_request_ready_to_respond(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_request_debug(req, "Ready to respond");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state = HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_connection_trigger_responses(req->conn);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid http_server_request_submit_response(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct http_server_connection *conn = req->conn;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen i_assert(conn != NULL && req->response != NULL && req->response->submitted);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (conn->payload_handler != NULL && conn->payload_handler->req == req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_payload_handler_destroy(&conn->payload_handler);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_request_debug(req, "Not ready to respond");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen req->state = HTTP_SERVER_REQUEST_STATE_SUBMITTED_RESPONSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen case HTTP_SERVER_REQUEST_STATE_READY_TO_RESPOND:
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_connection_trigger_responses(req->conn);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid http_server_request_finished(struct http_server_request *req)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct http_server_connection *conn = req->conn;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct http_server_response *resp = req->response;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen http_server_tunnel_callback_t tunnel_callback = resp->tunnel_callback;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen i_assert(req->state < HTTP_SERVER_REQUEST_STATE_FINISHED);
static struct http_server_response *
return resp;
struct http_server_istream {
static ssize_t
return ret;
struct istream *
bool blocking)
struct http_server_payload_handler_pump {
void (*callback)(void *);
void *context;
if (success) {
int ret;
if (ret < 0) {
struct http_server_payload_handler_raw {
void *context;