diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-09-23 22:03:57 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-09-24 10:56:19 +0200 |
| commit | cec24b0360d8a8a82ed2aa95362e958ec5f2fb0f (patch) | |
| tree | 4f986daba0ca35de0b9aebfc07fe849cc7fbeac2 | |
| parent | f7864cb7d49a8ca5bddf8d1f68b71ecd5ed85adc (diff) | |
WIP async responseasync-response
| -rw-r--r-- | handler.c | 15 | ||||
| -rw-r--r-- | http.c | 149 | ||||
| -rw-r--r-- | include/libweb/http.h | 1 |
3 files changed, 121 insertions, 44 deletions
@@ -28,6 +28,7 @@ struct handler struct handler *h; struct server_client *c; struct http_ctx *http; + int (*fn)(const struct http_payload *, struct http_response *, void *); struct client *next; } *clients; @@ -59,7 +60,19 @@ static int on_payload(const struct http_payload *const p, const struct elem *const e = &h->elem[i]; if (e->op == p->op && !wildcard_cmp(p->resource, e->url, true)) - return e->f(p, r, e->user); + { + int ret; + + if (c->fn) + ret = c->fn(p, r, e->user); + else + ret = e->f(p, r, e->user); + + if (!ret) + c->fn = r->step; + + return ret; + } } fprintf(stderr, "Not found: %s\n", p->resource); @@ -102,6 +102,7 @@ struct http_ctx size_t n_args, n_headers; struct http_header *headers; bool has_length, expect_continue; + int (*response)(struct http_ctx *); } ctx; struct write_ctx @@ -1211,15 +1212,22 @@ static int process_payload(struct http_ctx *const h) { struct ctx *const c = &h->ctx; const struct http_payload p = ctx_to_payload(c); + struct http_response *const r = &h->wctx.r; const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); - h->wctx.op = c->op; - ctx_free(c); - if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + h->wctx.op = c->op; + ctx_free(c); + return start_response(h); + } - return start_response(h); + return 0; } static int get_field_value(const char *const line, size_t *const n, @@ -1470,6 +1478,7 @@ static int check_length(struct http_ctx *const h) static int process_expect(struct http_ctx *const h) { struct ctx *const c = &h->ctx; + struct write_ctx *const w = &h->wctx; const int res = check_length(h); if (res) @@ -1480,7 +1489,7 @@ static int process_expect(struct http_ctx *const h) return res; } - h->wctx.close = true; + w->close = true; return start_response(h); } @@ -1488,36 +1497,51 @@ static int process_expect(struct http_ctx *const h) p.expect_continue = true; - const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); - - h->wctx.op = c->op; + struct http_response *const r = &h->wctx.r; + const int ret = h->cfg.payload(&p, r, h->cfg.user); if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + w->op = c->op; + c->state = BODY_LINE; + return start_response(h); + } - c->state = BODY_LINE; - return start_response(h); + return 0; } static int process_get(struct http_ctx *const h) { + int ret; struct ctx *const c = &h->ctx; struct http_payload p = ctx_to_payload(c); struct write_ctx *const w = &h->wctx; + struct http_response *const r = &w->r; p.u.get.range = w->gr = c->u2.get.range; - const int ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user); + if ((ret = h->cfg.payload(&p, &h->wctx.r, h->cfg.user))) + { + ctx_free(c); + return ret; + } + else if (!r->step) + { + w->op = c->op; + ctx_free(c); - w->op = c->op; - ctx_free(c); + if (w->gr.state) + w->r.status = HTTP_STATUS_PARTIAL_CONTENT; - if (ret) - return ret; - else if (w->gr.state) - w->r.status = HTTP_STATUS_PARTIAL_CONTENT; + return start_response(h); + } - return start_response(h); + return 0; } static int header_cr_line(struct http_ctx *const h) @@ -1530,17 +1554,25 @@ static int header_cr_line(struct http_ctx *const h) switch (c->op) { case HTTP_OP_GET: - return process_get(h); + c->response = process_get; + return 0; case HTTP_OP_HEAD: - return process_payload(h); + c->response = process_payload; + return 0; case HTTP_OP_POST: { if (!c->u2.payload.len) - return process_payload(h); + { + c->response = process_payload; + return 0; + } else if (c->expect_continue) - return process_expect(h); + { + c->response = process_expect; + return 0; + } else if (c->boundary) { const int res = check_length(h); @@ -1571,9 +1603,15 @@ static int header_cr_line(struct http_ctx *const h) return 1; } else if (!c->u2.payload.len) - return process_payload(h); + { + c->response = process_payload; + return 0; + } else if (c->expect_continue) - return process_expect(h); + { + c->response = process_expect; + return 0; + } c->state = BODY_LINE; return 0; @@ -1594,14 +1632,21 @@ static int send_payload(struct http_ctx *const h, const struct http_payload *const p) { struct ctx *const c = &h->ctx; - const int ret = h->cfg.payload(p, &h->wctx.r, h->cfg.user); - - ctx_free(c); + struct http_response *const r = &h->wctx.r; + const int ret = h->cfg.payload(p, r, h->cfg.user); if (ret) + { + ctx_free(c); return ret; + } + else if (!r->step) + { + ctx_free(c); + return start_response(h); + } - return start_response(h); + return 0; } static int update_lstate(struct http_ctx *const h, @@ -2216,7 +2261,7 @@ static int read_mf_end_boundary(struct http_ctx *const h, /* Found end boundary. */ if (!*n) - return end_boundary(h); + c->response = end_boundary; else m->state = MF_END_BOUNDARY_CR_LINE; } @@ -2243,7 +2288,8 @@ static int process_mf_end_crlf(struct http_ctx *const h) return 1; } - return end_boundary(h); + h->ctx.response = end_boundary; + return 0; } static int read_multiform(struct http_ctx *const h, const char *const buf, @@ -2284,6 +2330,15 @@ static int read_multiform(struct http_ctx *const h, const char *const buf, return 0; } +static int send_line_payload(struct http_ctx *const h) +{ + struct ctx *const c = &h->ctx; + struct http_payload pl = ctx_to_payload(c); + + pl.u.post.data = h->line; + return send_payload(h, &pl); +} + static int read_body_to_mem(struct http_ctx *const h, const char *const buf, size_t *const sz) { @@ -2302,11 +2357,8 @@ static int read_body_to_mem(struct http_ctx *const h, const char *const buf, if (p->read >= p->len) { - struct http_payload pl = ctx_to_payload(c); - h->line[p->len] = '\0'; - pl.u.post.data = h->line; - return send_payload(h, &pl); + c->response = send_line_payload; } return 0; @@ -2396,6 +2448,15 @@ static int read_put_body_to_file(struct http_ctx *const h, return 0; } +static int send_put_payload(struct http_ctx *const h) +{ + struct ctx *const c = &h->ctx; + struct http_payload pl = ctx_to_payload(c); + + pl.u.put.tmpname = c->u.put.tmpname; + return send_payload(h, &pl); +} + static int read_to_file(struct http_ctx *const h, const char *const buf, size_t *const sz) { @@ -2405,12 +2466,7 @@ static int read_to_file(struct http_ctx *const h, const char *const buf, if (read_put_body_to_file(h, buf, sz)) return -1; else if (p->read >= p->len) - { - struct http_payload pl = ctx_to_payload(c); - - pl.u.put.tmpname = c->u.put.tmpname; - return send_payload(h, &pl); - } + c->response = send_put_payload; return 0; } @@ -2547,12 +2603,19 @@ failure: int http_update(struct http_ctx *const h, bool *const write, bool *const close) { + int ret; + struct ctx *const c = &h->ctx; + struct write_ctx *const w = &h->wctx; + struct http_response *const r = &w->r; + *close = false; - struct write_ctx *const w = &h->wctx; - const int ret = w->pending ? http_write(h, close) : http_read(h, close); + if (c->response) + ret = c->response(h); + else + ret = w->pending ? http_write(h, close) : http_read(h, close); - *write = w->pending; + *write = c->response || w->pending; return ret; } diff --git a/include/libweb/http.h b/include/libweb/http.h index 736a561..f18b5c4 100644 --- a/include/libweb/http.h +++ b/include/libweb/http.h @@ -109,6 +109,7 @@ struct http_response unsigned long long n; size_t n_headers; void (*free)(void *); + int (*step)(const struct http_payload *, struct http_response *, void *); }; struct http_cfg |
