[mod_echo] test module to echo request as response

test/debugging module to echo request back to client as response

(not part of build Makefile)
personal/stbuehler/tests-path
Glenn Strauss 2021-08-21 10:05:42 -04:00
parent 6ed2777204
commit 517010f2a6
1 changed files with 145 additions and 0 deletions

145
src/mod_echo.c Normal file
View File

@ -0,0 +1,145 @@
/*
* 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;
}