diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-10-06 01:23:20 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-10-06 15:51:00 +0200 |
| commit | 3e4c7c993bbbe2bdeb563fa888b900d01c4be4a1 (patch) | |
| tree | bda2c376c19b11f8f76ef6aad84dea067f491934 /handler.c | |
| parent | a0f5f7509bb9040752fa61fe0fdb447608e22b1c (diff) | |
Fix design issues with async responses, add async example
struct http_response did not provide users any void * that could be used
to maintain a state between calls to an asynchronous HTTP response.
On the other hand, the user pointer could not be used for this purpose,
since it is shared among all HTTP clients for a given struct handler
instance.
Moreover, the length callback was still not supporting this feature,
which in fact might be required by some users. Implementing this was
particularly challenging, as this broke the current assumption that
all bytes on a call to http_read were being processed.
Now, since a client request can only be partially processed because of
the length callback, http_read must take this into account so that the
remaining bytes are still available for future calls, before reading
again from the file descriptor.
Diffstat (limited to 'handler.c')
| -rw-r--r-- | handler.c | 33 |
1 files changed, 26 insertions, 7 deletions
@@ -28,7 +28,8 @@ struct handler struct handler *h; struct server_client *c; struct http_ctx *http; - int (*fn)(const struct http_payload *, struct http_response *, void *); + union http_step step; + void *step_args; struct client *next; } *clients; @@ -61,15 +62,19 @@ static int on_payload(const struct http_payload *const p, if (e->op == p->op && !wildcard_cmp(p->resource, e->url, true)) { + union http_step *const s = &c->step; int ret; - if (c->fn) - ret = c->fn(p, r, e->user); + if (s->payload) + ret = s->payload(p, r, e->user, c->step_args); else ret = e->f(p, r, e->user); if (!ret) - c->fn = r->step; + { + s->payload = r->step.payload; + c->step_args = r->step_args; + } return ret; } @@ -92,10 +97,24 @@ static int on_length(const unsigned long long len, struct client *const cl = user; struct handler *const h = cl->h; - if (h->cfg.length) - return h->cfg.length(len, c, r, h->cfg.user); + if (!h->cfg.length) + return 0; - return 0; + union http_step *const s = &cl->step; + int ret; + + if (s->length) + ret = s->length(len, c, r, h->cfg.user, cl->step_args); + else + ret = h->cfg.length(len, c, r, h->cfg.user); + + if (!ret) + { + s->length = r->step.length; + cl->step_args = r->step_args; + } + + return ret; } static struct client *find_or_alloc_client(struct handler *const h, |
