View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0007242 | libmicrohttpd | HTTP 1.1 request pipelining | public | 2022-05-14 14:50 | 2023-02-08 15:33 |
| Reporter | gray | Assigned To | Christian Grothoff | ||
| Priority | normal | Severity | major | Reproducibility | always |
| Status | closed | Resolution | no change required | ||
| Product Version | 0.9.75 | ||||
| Target Version | 0.9.76 | Fixed in Version | 0.9.75 | ||
| Summary | 0007242: Connection: close is always set in response | ||||
| Description | Libmicrohttpd always sets "Connection: close" header in response to HTTP/1.1 requests. In my opinion, it is wrong, as HTTP 1.1 assumes keep-alive by defauit. Correct me if I'm wrong. The header is set to "close" because MHD_queue_response sets connection->discard_request to true in line 5261 of connection.c. Apparently, this tracks down to commit 78d0fb7b2. Before that, the "Connection:" header was set to "Keep-Alive", as expected. | ||||
| Steps To Reproduce | Attached is a trivial program implementing a HTTP server listening on port 8080. Compile and run it. From another console, run curl -v http://127.0.0.1:8080/. You will see "Connection: close" in response. When compiled with libmicrohttpd prior to commit 78d0fb7b2, Keep-Alive" would be returned instead. | ||||
| Tags | No tags attached. | ||||
| Attached Files | connclose.c (1,025 bytes)
#include <microhttpd.h>
#include <signal.h>
static enum MHD_Result
httpd_handler (void *cls,
struct MHD_Connection *conn,
const char *url, const char *method,
const char *version,
const char *upload_data, size_t *upload_data_size,
void **con_cls)
{
struct MHD_Response *response;
enum MHD_Result ret;
static char resp[] = "Response text";
response = MHD_create_response_from_buffer (sizeof (resp) - 1, resp, MHD_RESPMEM_PERSISTENT);
MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain");
ret = MHD_queue_response (conn, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
int
main (int argc, char **argv)
{
struct MHD_Daemon *mhd;
int port = 8080;
sigset_t sigs;
int i;
mhd = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
port,
NULL, NULL,
httpd_handler, NULL,
MHD_OPTION_END);
sigfillset (&sigs);
sigwait (&sigs, &i);
MHD_stop_daemon (mhd);
return 0;
}
| ||||
|
|
You're using the API wrong. You MUST NOT queue the response on the first callback *unless* you intend to return an error, prevent further uploads and close the connection. Correct usage of the API is attached (minimal modification to your code). With this, I can do: $ telnet localhost 8080 Trying ::1... Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.1 Host: localhost HTTP/1.1 200 OK Date: Wed, 08 Feb 2023 14:31:31 GMT Content-Type: text/plain Content-Length: 13 Response textGET / HTTP/1.1 Host: localhost HTTP/1.1 200 OK Date: Wed, 08 Feb 2023 14:31:41 GMT Content-Type: text/plain Content-Length: 13 Response text connclose-2.c (1,295 bytes)
#include <microhttpd.h>
#include <signal.h>
static enum MHD_Result
httpd_handler (void *cls,
struct MHD_Connection *conn,
const char *url, const char *method,
const char *version,
const char *upload_data, size_t *upload_data_size,
void **con_cls)
{
struct MHD_Response *response;
enum MHD_Result ret;
static char resp[] = "Response text";
if (NULL == *con_cls)
{
*con_cls = "not null";
return MHD_YES;
}
response = MHD_create_response_from_buffer (sizeof (resp) - 1, resp,
MHD_RESPMEM_PERSISTENT);
MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE,
"text/plain");
ret = MHD_queue_response (conn, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
int
main (int argc, char **argv)
{
struct MHD_Daemon *mhd;
int port = 8080;
sigset_t sigs;
int i;
mhd = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
port,
NULL, NULL,
httpd_handler, NULL,
MHD_OPTION_END);
sigfillset (&sigs);
sigwait (&sigs, &i);
MHD_stop_daemon (mhd);
return 0;
}
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2022-05-14 14:50 | gray | New Issue | |
| 2022-05-14 14:50 | gray | File Added: connclose.c | |
| 2023-02-08 15:32 | Christian Grothoff | Note Added: 0019782 | |
| 2023-02-08 15:32 | Christian Grothoff | File Added: connclose-2.c | |
| 2023-02-08 15:33 | Christian Grothoff | Assigned To | => Christian Grothoff |
| 2023-02-08 15:33 | Christian Grothoff | Status | new => resolved |
| 2023-02-08 15:33 | Christian Grothoff | Resolution | open => no change required |
| 2023-02-08 15:33 | Christian Grothoff | Fixed in Version | => 0.9.75 |
| 2023-02-08 15:33 | Christian Grothoff | Status | resolved => closed |
| 2023-02-08 15:33 | Christian Grothoff | Target Version | => 0.9.76 |