#include "http.h" #include "server.h" #include "slog.h" #include "cmd.h" #include #include #include void http_set_header(str_t *h, const char *p, size_t sz) { h->s = calloc(1, 1+sz); memcpy(h->s, p, sz); h->sz = sz; } /* HTTP Response */ void http_response_set_header(struct http_response *r, const char *k, const char *v) { int i, pos = r->header_count; size_t sz; char *s; sz = strlen(k) + 2 + strlen(v) + 2; s = calloc(sz + 1, 1); sprintf(s, "%s: %s\r\n", k, v); for(i = 0; i < r->header_count; ++i) { size_t klen = strlen(k); if(strncmp(r->headers[i].s, k, klen) == 0 && r->headers[i].s[klen] == ':') { pos = i; /* free old value before replacing it. */ free(r->headers[i].s); break; } } /* extend array */ if(pos == r->header_count) { r->headers = realloc(r->headers, sizeof(str_t)*(r->header_count + 1)); r->header_count++; } r->headers[pos].s = s; r->headers[pos].sz = sz; } void http_response_set_body(struct http_response *r, const char *body, size_t body_len) { r->body = body; r->body_len = body_len; } int http_response_write(struct http_response *r, int fd) { char *s = NULL, *p; size_t sz = 0; int i, ret; sz = sizeof("HTTP/1.x xxx ")-1 + strlen(r->msg) + 2; s = calloc(sz + 1, 1); ret = sprintf(s, "HTTP/1.1 %d %s\r\n", r->code, r->msg); p = s; // + ret - 3; if(r->code == 200 && r->body) { char content_length[10]; sprintf(content_length, "%zd", r->body_len); http_response_set_header(r, "Content-Length", content_length); } else { http_response_set_header(r, "Content-Length", "0"); } for(i = 0; i < r->header_count; ++i) { s = realloc(s, sz + r->headers[i].sz); p = s + sz; memcpy(p, r->headers[i].s, r->headers[i].sz); p += r->headers[i].sz; sz += r->headers[i].sz; } /* end of headers */ s = realloc(s, sz + 2); memcpy(s + sz, "\r\n", 2); sz += 2; if(r->body && r->body_len) { s = realloc(s, sz + r->body_len); memcpy(s + sz, r->body, r->body_len); sz += r->body_len; } ret = write(fd, s, sz); free(s); /* cleanup response object */ for(i = 0; i < r->header_count; ++i) { free(r->headers[i].s); } free(r->headers); return ret == (int)sz ? 0 : 1; }