Previously, this was only possible during response submission, which potentially requires making a `close' parameter available for any API function that submits a (failure) response.
This would become very ugly and inflexible.
bool payload_blocking:1;
bool payload_direct:1;
bool payload_corked:1;
- bool close:1;
bool submitted:1;
};
bool delay_destroy:1;
bool destroy_pending:1;
bool failed:1;
+ bool connection_close:1;
};
struct http_server_connection {
return FALSE;
}
+void http_server_request_connection_close(struct http_server_request *req,
+ bool close)
+{
+ i_assert(req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE);
+ req->connection_close = close;
+}
+
void http_server_request_destroy(struct http_server_request **_req)
{
struct http_server_request *req = *_req;
conn->stats.response_count++;
if (tunnel_callback == NULL) {
- if (resp->close) {
+ if (req->connection_close) {
http_server_connection_close(&conn,
t_strdup_printf("Server closed connection: %u %s",
resp->status, resp->reason));
static void
http_server_request_fail_full(struct http_server_request *req,
- unsigned int status, const char *reason, bool close)
+ unsigned int status, const char *reason)
{
struct http_server_response *resp;
req->failed = TRUE;
resp = http_server_request_create_fail_response(req, status, reason);
- if (close)
- http_server_response_submit_close(resp);
- else
- http_server_response_submit(resp);
+ http_server_response_submit(resp);
+ if (req->conn->input_broken)
+ req->connection_close = TRUE;
}
void http_server_request_fail(struct http_server_request *req,
unsigned int status, const char *reason)
{
- http_server_request_fail_full(req, status, reason, FALSE);
+ http_server_request_fail_full(req, status, reason);
}
void http_server_request_fail_close(struct http_server_request *req,
unsigned int status, const char *reason)
{
- http_server_request_fail_full(req, status, reason, TRUE);
+ http_server_request_connection_close(req, TRUE);
+ http_server_request_fail_full(req, status, reason);
}
void http_server_request_fail_auth(struct http_server_request *req,
http_server_response_add_auth(resp, &chlng);
}
-static void http_server_response_do_submit(struct http_server_response *resp,
- bool close)
+static void
+http_server_response_do_submit(struct http_server_response *resp)
{
+ i_assert(!resp->submitted);
if (resp->date == (time_t)-1)
resp->date = ioloop_time;
- resp->close = close;
resp->submitted = TRUE;
http_server_request_submit_response(resp->request);
}
void http_server_response_submit(struct http_server_response *resp)
{
- i_assert(!resp->submitted);
http_server_response_debug(resp, "Submitted");
- http_server_response_do_submit(resp, FALSE);
+ http_server_response_do_submit(resp);
}
void http_server_response_submit_close(struct http_server_response *resp)
{
- i_assert(!resp->submitted);
- http_server_response_debug(resp, "Submitted");
-
- http_server_response_do_submit(resp, TRUE);
+ http_server_request_connection_close(resp->request, TRUE);
+ http_server_response_submit(resp);
}
void http_server_response_submit_tunnel(struct http_server_response *resp,
http_server_tunnel_callback_t callback, void *context)
{
- i_assert(!resp->submitted);
http_server_response_debug(resp, "Started tunnelling");
resp->tunnel_callback = callback;
resp->tunnel_context = context;
- http_server_response_do_submit(resp, TRUE);
+ http_server_request_connection_close(resp->request, TRUE);
+ http_server_response_do_submit(resp);
}
static void
string_t *rtext = t_str_new(256);
struct const_iovec iov[3];
bool is_head = http_request_method_is(&req->req, "HEAD");
+ bool close = FALSE;
int ret = 0;
*error_r = NULL;
resp->payload_output = output;
o_stream_ref(output);
/* connection close marks end of payload */
- resp->close = TRUE;
+ close = TRUE;
}
} else {
if (!resp->have_hdr_body_spec)
str_append(rtext, "Content-Length: 0\r\n");
}
if (!resp->have_hdr_connection) {
- bool close = resp->close || req->req.connection_close ||
- req->conn->input_broken;
+ close = close || req->req.connection_close ||
+ req->connection_close || req->conn->input_broken;
if (close && resp->tunnel_callback == NULL)
str_append(rtext, "Connection: close\r\n");
else if (http_server_request_version_equals(req, 1, 0))
references, FALSE if not. */
bool http_server_request_unref(struct http_server_request **_req);
+/* Set flag that determines whether the connection is closed after the
+ request is handled. */
+void http_server_request_connection_close(struct http_server_request *req,
+ bool close);
+
/* Get the pool for this request. */
pool_t http_server_request_get_pool(struct http_server_request *req);
/* Returns the response created for the request with