lighttpd 1.4.x
https://www.lighttpd.net/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.4 KiB
145 lines
4.4 KiB
/* |
|
* mod_echo - test/debugging module to echo request back to client as response |
|
* |
|
* Copyright(c) 2021 Glenn Strauss gstrauss()gluelogic.com All rights reserved |
|
* License: BSD 3-clause (same as lighttpd) |
|
* |
|
* Note: module is hard-coded to handle requests to the exact uri-path: "/echo" |
|
* |
|
* Note: testing GET requests with Content-Length requires lighttpd.conf: |
|
* server.http-parseopts += ("method-get-body" => "enable") |
|
*/ |
|
#include "first.h" |
|
|
|
#include <stdlib.h> |
|
|
|
#include "base.h" |
|
#include "fdevent.h" |
|
#include "http_chunk.h" |
|
#include "plugin.h" |
|
#include "request.h" |
|
#include "response.h" |
|
|
|
typedef struct { |
|
PLUGIN_DATA; |
|
} plugin_data; |
|
|
|
INIT_FUNC(mod_echo_init) { |
|
return calloc(1, sizeof(plugin_data)); |
|
} |
|
|
|
#if 1 /*(would be simpler if not supporting streaming w/ bufmin)*/ |
|
|
|
static handler_t mod_echo_request_body(request_st * const r) { |
|
chunkqueue * const cq = &r->reqbody_queue; |
|
chunkqueue_remove_finished_chunks(cq); /* unnecessary? */ |
|
off_t cqlen = chunkqueue_length(cq); |
|
if ((r->conf.stream_response_body & FDEVENT_STREAM_RESPONSE_BUFMIN) |
|
&& r->resp_body_started) { |
|
if (chunkqueue_length(&r->write_queue) > 65536 - 4096) { |
|
/* wait for more data to be sent to client */ |
|
return HANDLER_WAIT_FOR_EVENT; |
|
} |
|
else { |
|
if (cqlen > 65536) { |
|
cqlen = 65536; |
|
joblist_append(r->con); |
|
} |
|
} |
|
} |
|
|
|
if (0 != http_chunk_transfer_cqlen(r, cq, (size_t)cqlen)) |
|
return HANDLER_ERROR; |
|
|
|
if (cq->bytes_out == (off_t)r->reqbody_length) { |
|
/* sent all request body input */ |
|
http_response_backend_done(r); |
|
return HANDLER_FINISHED; |
|
} |
|
|
|
cqlen = chunkqueue_length(cq); |
|
if (cq->bytes_in != (off_t)r->reqbody_length && cqlen < 65536 - 16384) { |
|
/*(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST)*/ |
|
if (!(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN)) { |
|
r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN; |
|
r->con->is_readable = 1; /* trigger optimistic read from client */ |
|
} |
|
} |
|
return HANDLER_WAIT_FOR_EVENT; |
|
} |
|
|
|
SUBREQUEST_FUNC(mod_echo_handle_subrequest) { |
|
UNUSED(p_d); |
|
|
|
handler_t rc = mod_echo_request_body(r); |
|
if (rc != HANDLER_WAIT_FOR_EVENT) return rc; |
|
|
|
chunkqueue * const cq = &r->reqbody_queue; |
|
if (cq->bytes_in != (off_t)r->reqbody_length) { |
|
/*(64k - 4k to attempt to avoid temporary files |
|
* in conjunction with FDEVENT_STREAM_REQUEST_BUFMIN)*/ |
|
if (chunkqueue_length(cq) > 65536 - 4096 |
|
&& (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN)) { |
|
r->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN; |
|
return HANDLER_WAIT_FOR_EVENT; |
|
} |
|
else { |
|
rc = r->con->reqbody_read(r); |
|
if (rc != HANDLER_GO_ON) return rc; |
|
|
|
if (-1 == r->reqbody_length |
|
&& !(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST)) |
|
return HANDLER_WAIT_FOR_EVENT; |
|
} |
|
} |
|
|
|
return mod_echo_request_body(r); |
|
} |
|
|
|
#else /*(would be simpler if not supporting streaming w/ bufmin (above))*/ |
|
|
|
SUBREQUEST_FUNC(mod_echo_handle_subrequest) { |
|
UNUSED(p_d); |
|
|
|
handler_t rc = r->con->reqbody_read(r); |
|
if (rc != HANDLER_GO_ON) return rc; |
|
|
|
chunkqueue * const cq = &r->reqbody_queue; |
|
if (0 != http_chunk_transfer_cqlen(r, cq, chunkqueue_length(cq))) |
|
return HANDLER_ERROR; |
|
|
|
if (cq->bytes_out == (off_t)r->reqbody_length) { |
|
http_response_backend_done(r); |
|
return HANDLER_FINISHED; |
|
} |
|
return HANDLER_WAIT_FOR_EVENT; |
|
} |
|
|
|
#endif |
|
|
|
URIHANDLER_FUNC(mod_echo_handle_uri_clean) { |
|
plugin_data *p = p_d; |
|
if (NULL == r->handler_module |
|
&& buffer_eq_slen(&r->uri.path, CONST_STR_LEN("/echo"))) { |
|
r->handler_module = p->self; |
|
r->resp_body_started = 1; |
|
/* XXX: future: might echo request headers here */ |
|
if (0 == r->reqbody_length) { |
|
r->resp_body_finished = 1; |
|
return HANDLER_FINISHED; |
|
} |
|
} |
|
return HANDLER_GO_ON; |
|
} |
|
|
|
int mod_echo_plugin_init(plugin *p); |
|
int mod_echo_plugin_init(plugin *p) { |
|
p->version = LIGHTTPD_VERSION_ID; |
|
p->name = "echo"; |
|
|
|
p->handle_uri_clean = mod_echo_handle_uri_clean; |
|
p->handle_subrequest = mod_echo_handle_subrequest; |
|
p->init = mod_echo_init; |
|
|
|
return 0; |
|
}
|
|
|