|
|
@ -19,6 +19,7 @@ http_response_init(struct worker *w, int code, const char *msg) {
|
|
|
|
r->code = code;
|
|
|
|
r->code = code;
|
|
|
|
r->msg = msg;
|
|
|
|
r->msg = msg;
|
|
|
|
r->w = w;
|
|
|
|
r->w = w;
|
|
|
|
|
|
|
|
r->keep_alive = 0; /* default */
|
|
|
|
|
|
|
|
|
|
|
|
http_response_set_header(r, "Server", "Webdis");
|
|
|
|
http_response_set_header(r, "Server", "Webdis");
|
|
|
|
|
|
|
|
|
|
|
@ -131,13 +132,31 @@ http_schedule_write(int fd, struct http_response *r) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
|
|
|
format_chunk(const char *p, size_t sz, size_t *out_sz) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *out, tmp[64];
|
|
|
|
|
|
|
|
int chunk_size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate format size */
|
|
|
|
|
|
|
|
chunk_size = sprintf(tmp, "%x\r\n", (int)sz);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*out_sz = chunk_size + sz + 2;
|
|
|
|
|
|
|
|
out = malloc(*out_sz);
|
|
|
|
|
|
|
|
memcpy(out, tmp, chunk_size);
|
|
|
|
|
|
|
|
memcpy(out + chunk_size, p, sz);
|
|
|
|
|
|
|
|
memcpy(out + chunk_size + sz, "\r\n", 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return out;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
http_response_write(struct http_response *r, int fd) {
|
|
|
|
http_response_write(struct http_response *r, int fd) {
|
|
|
|
|
|
|
|
|
|
|
|
char *p;
|
|
|
|
char *p;
|
|
|
|
int i, ret;
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
|
|
r->keep_alive = 0;
|
|
|
|
/*r->keep_alive = 0;*/
|
|
|
|
r->out_sz = sizeof("HTTP/1.x xxx ")-1 + strlen(r->msg) + 2;
|
|
|
|
r->out_sz = sizeof("HTTP/1.x xxx ")-1 + strlen(r->msg) + 2;
|
|
|
|
r->out = calloc(r->out_sz + 1, 1);
|
|
|
|
r->out = calloc(r->out_sz + 1, 1);
|
|
|
|
|
|
|
|
|
|
|
@ -145,13 +164,15 @@ http_response_write(struct http_response *r, int fd) {
|
|
|
|
(void)ret;
|
|
|
|
(void)ret;
|
|
|
|
p = r->out;
|
|
|
|
p = r->out;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!r->chunked) {
|
|
|
|
if(r->code == 200 && r->body) {
|
|
|
|
if(r->code == 200 && r->body) {
|
|
|
|
char content_length[10];
|
|
|
|
char content_length[10];
|
|
|
|
sprintf(content_length, "%zd", r->body_len);
|
|
|
|
sprintf(content_length, "%zd", r->body_len);
|
|
|
|
http_response_set_header(r, "Content-Length", content_length);
|
|
|
|
http_response_set_header(r, "Content-Length", content_length);
|
|
|
|
} else if(!r->chunked) {
|
|
|
|
} else {
|
|
|
|
http_response_set_header(r, "Content-Length", "0");
|
|
|
|
http_response_set_header(r, "Content-Length", "0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < r->header_count; ++i) {
|
|
|
|
for(i = 0; i < r->header_count; ++i) {
|
|
|
|
/* "Key: Value\r\n" */
|
|
|
|
/* "Key: Value\r\n" */
|
|
|
@ -190,9 +211,20 @@ http_response_write(struct http_response *r, int fd) {
|
|
|
|
|
|
|
|
|
|
|
|
/* append body if there is one. */
|
|
|
|
/* append body if there is one. */
|
|
|
|
if(r->body && r->body_len) {
|
|
|
|
if(r->body && r->body_len) {
|
|
|
|
r->out = realloc(r->out, r->out_sz + r->body_len);
|
|
|
|
|
|
|
|
memcpy(r->out + r->out_sz, r->body, r->body_len);
|
|
|
|
char *tmp = (char*)r->body;
|
|
|
|
r->out_sz += r->body_len;
|
|
|
|
size_t tmp_len = r->body_len;
|
|
|
|
|
|
|
|
if(r->chunked) { /* replace body with formatted chunk */
|
|
|
|
|
|
|
|
tmp = format_chunk(r->body, r->body_len, &tmp_len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r->out = realloc(r->out, r->out_sz + tmp_len);
|
|
|
|
|
|
|
|
memcpy(r->out + r->out_sz, tmp, tmp_len);
|
|
|
|
|
|
|
|
r->out_sz += tmp_len;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(r->chunked) { /* need to free the chunk */
|
|
|
|
|
|
|
|
free(tmp);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* send buffer to client */
|
|
|
|
/* send buffer to client */
|
|
|
@ -245,6 +277,7 @@ http_send_error(struct http_client *c, short code, const char *msg) {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
void
|
|
|
|
http_response_set_keep_alive(struct http_response *r, int enabled) {
|
|
|
|
http_response_set_keep_alive(struct http_response *r, int enabled) {
|
|
|
|
|
|
|
|
r->keep_alive = enabled;
|
|
|
|
if(enabled) {
|
|
|
|
if(enabled) {
|
|
|
|
http_response_set_header(r, "Connection", "Keep-Alive");
|
|
|
|
http_response_set_header(r, "Connection", "Keep-Alive");
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -273,25 +306,13 @@ http_send_options(struct http_client *c) {
|
|
|
|
void
|
|
|
|
void
|
|
|
|
http_response_write_chunk(int fd, struct worker *w, const char *p, size_t sz) {
|
|
|
|
http_response_write_chunk(int fd, struct worker *w, const char *p, size_t sz) {
|
|
|
|
|
|
|
|
|
|
|
|
char *out, tmp[64];
|
|
|
|
|
|
|
|
size_t out_sz;
|
|
|
|
|
|
|
|
int chunk_size;
|
|
|
|
|
|
|
|
struct http_response *r = http_response_init(w, 0, NULL);
|
|
|
|
struct http_response *r = http_response_init(w, 0, NULL);
|
|
|
|
|
|
|
|
r->keep_alive = 1; /* chunks are always keep-alive */
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate format size */
|
|
|
|
/* format packet */
|
|
|
|
chunk_size = sprintf(tmp, "%x\r\n", (int)sz);
|
|
|
|
r->out = format_chunk(p, sz, &r->out_sz);
|
|
|
|
|
|
|
|
|
|
|
|
out_sz = chunk_size + sz + 2;
|
|
|
|
|
|
|
|
out = malloc(out_sz);
|
|
|
|
|
|
|
|
memcpy(out, tmp, chunk_size);
|
|
|
|
|
|
|
|
memcpy(out + chunk_size, p, sz);
|
|
|
|
|
|
|
|
memcpy(out + chunk_size + sz, "\r\n", 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* send async write */
|
|
|
|
/* send async write */
|
|
|
|
r->out = out;
|
|
|
|
|
|
|
|
r->out_sz = out_sz;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
http_schedule_write(fd, r);
|
|
|
|
http_schedule_write(fd, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|