Implement HEAD support

This commit is contained in:
Xavier Del Campo Romero 2023-10-03 00:09:37 +02:00
parent 1d2ce3f9c2
commit 472b4ddbf1
Signed by: xavi
GPG Key ID: 84FF3612A9BF43F2
3 changed files with 90 additions and 0 deletions

56
main.c
View File

@ -980,6 +980,61 @@ end:
return ret;
}
static int getnode_head(const struct http_payload *const p,
struct http_response *const r, void *const user)
{
struct auth *const a = user;
if (auth_cookie(a, &p->cookie))
{
fprintf(stderr, "%s: auth_cookie failed\n", __func__);
return page_forbidden(r);
}
const char *const username = p->cookie.field,
*const resource = p->resource + strlen("/user/");
if (path_invalid(resource))
{
fprintf(stderr, "%s: illegal relative path %s\n", __func__, resource);
return page_forbidden(r);
}
int ret = -1;
struct dynstr dir, root, d;
const char *const adir = auth_dir(a),
*const sep = p->resource[strlen(p->resource) - 1] != '/' ? "/" : "";
dynstr_init(&dir);
dynstr_init(&d);
dynstr_init(&root);
if (!adir)
{
fprintf(stderr, "%s: auth_dir failed\n", __func__);
goto end;
}
else if (dynstr_append(&dir, "%s%s", p->resource, sep))
{
fprintf(stderr, "%s: dynstr_append dird failed\n", __func__);
goto end;
}
else if (dynstr_append(&root, "%s/user/%s/", adir, username)
|| dynstr_append(&d, "%s%s", root.str, resource))
{
fprintf(stderr, "%s: dynstr_append failed\n", __func__);
goto end;
}
ret = page_head_resource(r, d.str);
end:
dynstr_free(&dir);
dynstr_free(&d);
dynstr_free(&root);
return ret;
}
static int move_file(const char *const old, const char *const new)
{
int ret = -1;
@ -1924,6 +1979,7 @@ static int add_urls(struct handler *const h, void *const user)
{.url = "/index.html", .op = HTTP_OP_GET, .f = serve_index},
{.url = "/style.css", .op = HTTP_OP_GET, .f = serve_style},
{.url = "/user/*", .op = HTTP_OP_GET, .f = getnode},
{.url = "/user/*", .op = HTTP_OP_HEAD, .f = getnode_head},
{.url = "/login", .op = HTTP_OP_POST, .f = login},
{.url = "/logout", .op = HTTP_OP_POST, .f = logout},
{.url = "/public/*", .op = HTTP_OP_GET, .f = getpublic},

33
page.c
View File

@ -2199,3 +2199,36 @@ end:
return ret;
}
int page_head_resource(struct http_response *const r, const char *const res)
{
struct stat sb;
if (stat(res, &sb))
{
if (errno == ENOENT || errno == ENOTDIR)
return page_not_found(r);
else
{
fprintf(stderr, "%s: stat(2) %s: %s\n",
__func__, res, strerror(errno));
return -1;
}
}
const mode_t m = sb.st_mode;
if (!S_ISDIR(m) && !S_ISREG(m))
{
fprintf(stderr, "%s: unexpected st_mode %jd\n", __func__, (intmax_t)m);
return -1;
}
*r = (const struct http_response)
{
.status = HTTP_STATUS_OK,
.n = sb.st_size
};
return 0;
}

1
page.h
View File

@ -43,6 +43,7 @@ int page_failed_login(struct http_response *r);
int page_forbidden(struct http_response *r);
int page_bad_request(struct http_response *r);
int page_resource(const struct page_resource *r);
int page_head_resource(struct http_response *r, const char *res);
int page_public(struct http_response *r, const char *res);
int page_share(struct http_response *r, const char *path);
int page_quota_exceeded(struct http_response *r, unsigned long long len,