mirror of
https://github.com/jorisvink/kore
synced 2025-03-09 12:39:01 -04:00
allow modules to add headers to the response before calling http_response()
by calling http_response_header_add(). fix wrong overflow check in spdy_stream_get_header(). html_inject now exports last modified timestamp for the files that are compiled into the module in the format static_mtime_<type>_<name>. modules can now look into the request headers using http_request_header_get().
This commit is contained in:
parent
a228cdba0e
commit
a9ebf37cae
@ -47,9 +47,27 @@ int
|
||||
betrippin_serve_style_css(struct http_request *req)
|
||||
{
|
||||
int ret;
|
||||
char *date;
|
||||
time_t tstamp;
|
||||
|
||||
ret = http_response(req, 200, static_css_style,
|
||||
static_len_css_style, "text/css");
|
||||
if (http_request_header_get(req, "if-modified-since", &date)) {
|
||||
tstamp = kore_date_to_time(date);
|
||||
free(date);
|
||||
|
||||
kore_log("header was present with %ld", tstamp);
|
||||
}
|
||||
|
||||
if (tstamp != 0 && tstamp <= static_mtime_css_style) {
|
||||
ret = http_response(req, 304, NULL, 0);
|
||||
} else {
|
||||
date = kore_time_to_date(static_mtime_css_style);
|
||||
if (date != NULL)
|
||||
http_response_header_add(req, "last-modified", date);
|
||||
|
||||
http_response_header_add(req, "content-type", "text/css");
|
||||
ret = http_response(req, 200, static_css_style,
|
||||
static_len_css_style);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@ -59,8 +77,9 @@ betrippin_serve_index(struct http_request *req)
|
||||
{
|
||||
int ret;
|
||||
|
||||
http_response_header_add(req, "content-type", "text/html");
|
||||
ret = http_response(req, 200, static_html_index,
|
||||
static_len_html_index, "text/html");
|
||||
static_len_html_index);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
@ -27,6 +28,7 @@
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat st;
|
||||
size_t len;
|
||||
FILE *fp, *hdr;
|
||||
char *ext, *p, *c, buf[1024];
|
||||
@ -40,6 +42,11 @@ main(int argc, char *argv[])
|
||||
if ((ext = strchr(argv[2], '.')) != NULL)
|
||||
*(ext)++ = '\0';
|
||||
|
||||
if (stat(argv[1], &st) == -1) {
|
||||
printf("stat(%s) failed: %d\n", argv[1], errno);
|
||||
exit(99);
|
||||
}
|
||||
|
||||
printf("/**** AUTO GENERATED BY MAKEFILE - DO NOT TOUCH ****/\n");
|
||||
printf("#include <sys/param.h>\n\n");
|
||||
printf("u_int8_t *static_%s_%s = (u_int8_t *)", ext, argv[2]);
|
||||
@ -64,10 +71,12 @@ main(int argc, char *argv[])
|
||||
fclose(fp);
|
||||
|
||||
printf(";\n\n");
|
||||
printf("u_int32_t static_len_%s_%s = %ld;", ext, argv[2], len);
|
||||
printf("u_int32_t static_len_%s_%s = %ld;\n", ext, argv[2], len);
|
||||
printf("time_t static_mtime_%s_%s = %ld;\n", ext, argv[2], st.st_mtime);
|
||||
|
||||
fprintf(hdr, "extern u_int8_t *static_%s_%s;\n", ext, argv[2]);
|
||||
fprintf(hdr, "extern u_int32_t static_len_%s_%s;\n", ext, argv[2]);
|
||||
fprintf(hdr, "extern u_int32_t static_mtime_%s_%s;\n", ext, argv[2]);
|
||||
fclose(hdr);
|
||||
|
||||
return (0);
|
||||
|
@ -17,6 +17,13 @@
|
||||
#ifndef __H_HTTP_H
|
||||
#define __H_HTTP_H
|
||||
|
||||
struct http_header {
|
||||
char *header;
|
||||
char *value;
|
||||
|
||||
TAILQ_ENTRY(http_header) list;
|
||||
};
|
||||
|
||||
struct http_request {
|
||||
char *host;
|
||||
char *method;
|
||||
@ -25,6 +32,7 @@ struct http_request {
|
||||
struct connection *owner;
|
||||
struct spdy_stream *stream;
|
||||
|
||||
TAILQ_HEAD(, http_header) headers;
|
||||
TAILQ_ENTRY(http_request) list;
|
||||
};
|
||||
|
||||
@ -33,8 +41,10 @@ void http_process(void);
|
||||
time_t http_date_to_time(char *);
|
||||
void http_request_free(struct http_request *);
|
||||
int http_response(struct http_request *, int,
|
||||
u_int8_t *, u_int32_t, char *);
|
||||
int http_new_request(struct connection *, struct spdy_stream *,
|
||||
u_int8_t *, u_int32_t);
|
||||
int http_request_header_get(struct http_request *, char *, char **);
|
||||
void http_response_header_add(struct http_request *, char *, char *);
|
||||
int http_request_new(struct connection *, struct spdy_stream *,
|
||||
char *, char *, char *);
|
||||
|
||||
#endif /* !__H_HTTP_H */
|
||||
|
@ -96,6 +96,7 @@ void *kore_malloc(size_t);
|
||||
void *kore_calloc(size_t, size_t);
|
||||
void *kore_realloc(void *, size_t);
|
||||
time_t kore_date_to_time(char *);
|
||||
char *kore_time_to_date(time_t);
|
||||
char *kore_strdup(const char *);
|
||||
void kore_parse_config(const char *);
|
||||
void kore_strlcpy(char *, const char *, size_t);
|
||||
@ -126,8 +127,10 @@ int net_recv_expand(struct connection *c, struct netbuf *, size_t,
|
||||
int net_send_queue(struct connection *, u_int8_t *, size_t,
|
||||
struct netbuf **, int (*cb)(struct netbuf *));
|
||||
|
||||
struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t);
|
||||
struct spdy_header_block *spdy_header_block_create(int);
|
||||
struct spdy_stream *spdy_stream_lookup(struct connection *, u_int32_t);
|
||||
int spdy_stream_get_header(struct spdy_header_block *,
|
||||
char *, char **);
|
||||
|
||||
int spdy_frame_recv(struct netbuf *);
|
||||
int spdy_frame_send(struct connection *, u_int16_t,
|
||||
|
60
src/http.c
60
src/http.c
@ -49,12 +49,12 @@ http_init(void)
|
||||
}
|
||||
|
||||
int
|
||||
http_new_request(struct connection *c, struct spdy_stream *s, char *host,
|
||||
http_request_new(struct connection *c, struct spdy_stream *s, char *host,
|
||||
char *method, char *path)
|
||||
{
|
||||
struct http_request *req;
|
||||
|
||||
kore_log("http_new_request(%p, %p, %s, %s, %s)", c, s,
|
||||
kore_log("http_request_new(%p, %p, %s, %s, %s)", c, s,
|
||||
host, method, path);
|
||||
|
||||
req = (struct http_request *)kore_malloc(sizeof(*req));
|
||||
@ -63,14 +63,39 @@ http_new_request(struct connection *c, struct spdy_stream *s, char *host,
|
||||
req->host = kore_strdup(host);
|
||||
req->path = kore_strdup(path);
|
||||
req->method = kore_strdup(method);
|
||||
TAILQ_INIT(&(req->headers));
|
||||
TAILQ_INSERT_TAIL(&http_requests, req, list);
|
||||
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
void
|
||||
http_response_header_add(struct http_request *req, char *header, char *value)
|
||||
{
|
||||
struct http_header *hdr;
|
||||
|
||||
kore_log("http_response_header_add(%p, %s, %s)", req, header, value);
|
||||
|
||||
hdr = (struct http_header *)kore_malloc(sizeof(*hdr));
|
||||
hdr->header = kore_strdup(header);
|
||||
hdr->value = kore_strdup(value);
|
||||
TAILQ_INSERT_TAIL(&(req->headers), hdr, list);
|
||||
}
|
||||
|
||||
void
|
||||
http_request_free(struct http_request *req)
|
||||
{
|
||||
struct http_header *hdr, *next;
|
||||
|
||||
for (hdr = TAILQ_FIRST(&(req->headers)); hdr != NULL; hdr = next) {
|
||||
next = TAILQ_NEXT(hdr, list);
|
||||
|
||||
TAILQ_REMOVE(&(req->headers), hdr, list);
|
||||
free(hdr->header);
|
||||
free(hdr->value);
|
||||
free(hdr);
|
||||
}
|
||||
|
||||
free(req->method);
|
||||
free(req->path);
|
||||
free(req->host);
|
||||
@ -78,25 +103,25 @@ http_request_free(struct http_request *req)
|
||||
}
|
||||
|
||||
int
|
||||
http_response(struct http_request *req, int status, u_int8_t *d,
|
||||
u_int32_t len, char *content_type)
|
||||
http_response(struct http_request *req, int status, u_int8_t *d, u_int32_t len)
|
||||
{
|
||||
u_int32_t hlen;
|
||||
struct http_header *hdr;
|
||||
u_int8_t *htext;
|
||||
char sbuf[4];
|
||||
struct spdy_header_block *hblock;
|
||||
char sbuf[4];
|
||||
|
||||
kore_log("http_response(%p, %d, %p, %d)", req, status, d, len);
|
||||
|
||||
if (req->owner->proto == CONN_PROTO_SPDY) {
|
||||
snprintf(sbuf, sizeof(sbuf), "%d", status);
|
||||
|
||||
hblock = spdy_header_block_create(SPDY_HBLOCK_NORMAL);
|
||||
spdy_header_block_add(hblock, ":status", sbuf);
|
||||
spdy_header_block_add(hblock, ":version", "HTTP/1.1");
|
||||
if (content_type != NULL) {
|
||||
spdy_header_block_add(hblock,
|
||||
"content-type", content_type);
|
||||
}
|
||||
TAILQ_FOREACH(hdr, &(req->headers), list)
|
||||
spdy_header_block_add(hblock, hdr->header, hdr->value);
|
||||
|
||||
htext = spdy_header_block_release(req->owner, hblock, &hlen);
|
||||
if (htext == NULL)
|
||||
return (KORE_RESULT_ERROR);
|
||||
@ -126,6 +151,21 @@ http_response(struct http_request *req, int status, u_int8_t *d,
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
int
|
||||
http_request_header_get(struct http_request *req, char *header, char **out)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (req->owner->proto == CONN_PROTO_SPDY) {
|
||||
r = spdy_stream_get_header(req->stream->hblock, header, out);
|
||||
} else {
|
||||
kore_log("http not supported yet");
|
||||
r = KORE_RESULT_ERROR;
|
||||
}
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
http_process(void)
|
||||
{
|
||||
@ -160,5 +200,5 @@ http_generic_404(struct http_request *req)
|
||||
kore_log("http_generic_404(%s, %s, %s)",
|
||||
req->host, req->method, req->path);
|
||||
|
||||
return (http_response(req, 404, NULL, 0, NULL));
|
||||
return (http_response(req, 404, NULL, 0));
|
||||
}
|
||||
|
103
src/spdy.c
103
src/spdy.c
@ -40,8 +40,6 @@
|
||||
static int spdy_ctrl_frame_syn_stream(struct netbuf *);
|
||||
static int spdy_ctrl_frame_settings(struct netbuf *);
|
||||
static int spdy_ctrl_frame_ping(struct netbuf *);
|
||||
static int spdy_stream_get_header(struct spdy_header_block *,
|
||||
char *, char **);
|
||||
|
||||
static int spdy_zlib_inflate(struct connection *, u_int8_t *,
|
||||
size_t, u_int8_t **, u_int32_t *);
|
||||
@ -237,6 +235,59 @@ spdy_header_block_release(struct connection *c,
|
||||
return (deflated);
|
||||
}
|
||||
|
||||
int
|
||||
spdy_stream_get_header(struct spdy_header_block *s, char *header, char **out)
|
||||
{
|
||||
char *cmp, t[128];
|
||||
u_int8_t *p, *end;
|
||||
u_int32_t i, nlen, vlen;
|
||||
|
||||
kore_log("spdy_stream_get_header(%p, %s) <%d>", s, header,
|
||||
s->header_pairs);
|
||||
|
||||
p = s->header_block + 4;
|
||||
end = s->header_block + s->header_block_len;
|
||||
|
||||
if (p >= end) {
|
||||
kore_log("p >= end when looking for headers");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
for (i = 0; i < s->header_pairs; i++) {
|
||||
nlen = net_read32(p);
|
||||
if ((p + nlen + 4) > end) {
|
||||
kore_log("nlen out of bounds on %d (%d)", i, nlen);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
vlen = net_read32(p + nlen + 4);
|
||||
if ((p + nlen + vlen + 8) > end) {
|
||||
kore_log("vlen out of bounds on %d (%d)", i, vlen);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
cmp = (char *)(p + 4);
|
||||
memcpy(t, cmp, nlen);
|
||||
t[nlen] = '\0';
|
||||
kore_log("header %s", t);
|
||||
|
||||
if (!strncasecmp(cmp, header, nlen)) {
|
||||
kore_log("found %s header", header);
|
||||
|
||||
cmp = (char *)(p + nlen + 8);
|
||||
*out = (char *)kore_malloc(vlen + 1);
|
||||
kore_strlcpy(*out, cmp, vlen + 1);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
kore_log("pair name %d bytes, value %d bytes", nlen, vlen);
|
||||
|
||||
p += nlen + vlen + 8;
|
||||
}
|
||||
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
static int
|
||||
spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
||||
{
|
||||
@ -321,7 +372,7 @@ spdy_ctrl_frame_syn_stream(struct netbuf *nb)
|
||||
GET_HEADER(":path", &path);
|
||||
GET_HEADER(":method", &method);
|
||||
GET_HEADER(":host", &host);
|
||||
if (!http_new_request(c, s, host, method, path)) {
|
||||
if (!http_request_new(c, s, host, method, path)) {
|
||||
free(s->hblock->header_block);
|
||||
free(s->hblock);
|
||||
free(s);
|
||||
@ -365,52 +416,6 @@ spdy_ctrl_frame_ping(struct netbuf *nb)
|
||||
return (spdy_frame_send(c, SPDY_CTRL_FRAME_PING, 0, 4, id));
|
||||
}
|
||||
|
||||
static int
|
||||
spdy_stream_get_header(struct spdy_header_block *s, char *header, char **out)
|
||||
{
|
||||
char *cmp;
|
||||
u_int8_t *p, *end;
|
||||
u_int32_t i, nlen, vlen;
|
||||
|
||||
p = s->header_block + 4;
|
||||
end = s->header_block + s->header_block_len;
|
||||
|
||||
if (p >= end) {
|
||||
kore_log("p >= end when looking for headers");
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
for (i = 0; i < s->header_pairs; i++) {
|
||||
nlen = net_read32(p);
|
||||
if ((p + nlen + 4) >= end) {
|
||||
kore_log("nlen out of bounds (%d)", nlen);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
vlen = net_read32(p + nlen + 4);
|
||||
if ((p + nlen + vlen + 8) >= end) {
|
||||
kore_log("vlen out of bounds (%d)", vlen);
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
cmp = (char *)(p + 4);
|
||||
if (!strncasecmp(cmp, header, nlen)) {
|
||||
kore_log("found %s header", header);
|
||||
|
||||
cmp = (char *)(p + nlen + 8);
|
||||
*out = (char *)kore_malloc(vlen + 1);
|
||||
kore_strlcpy(*out, cmp, vlen + 1);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
kore_log("pair name %d bytes, value %d bytes", nlen, vlen);
|
||||
|
||||
p += nlen + vlen + 8;
|
||||
}
|
||||
|
||||
return (KORE_RESULT_ERROR);
|
||||
}
|
||||
|
||||
static int
|
||||
spdy_zlib_inflate(struct connection *c, u_int8_t *src, size_t len,
|
||||
u_int8_t **dst, u_int32_t *olen)
|
||||
|
20
src/utils.c
20
src/utils.c
@ -255,6 +255,26 @@ out:
|
||||
return (t);
|
||||
}
|
||||
|
||||
char *
|
||||
kore_time_to_date(time_t now)
|
||||
{
|
||||
struct tm *tm;
|
||||
static time_t last = 0;
|
||||
static char tbuf[32];
|
||||
|
||||
if (now != last) {
|
||||
last = now;
|
||||
|
||||
tm = gmtime(&now);
|
||||
if (!strftime(tbuf, sizeof(tbuf), "%a, %d %b %Y %T GMT", tm)) {
|
||||
kore_log("strftime() gave us NULL (%ld)", now);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (tbuf);
|
||||
}
|
||||
|
||||
void
|
||||
fatal(const char *fmt, ...)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user