Fix a couple more bugs in new HTTP server code

This commit is contained in:
Andrew Bettison 2013-10-25 23:57:23 +10:30
parent 6488f7ad65
commit 5ff5a02bb9
4 changed files with 34 additions and 18 deletions

View File

@ -1590,18 +1590,18 @@ static void http_request_start_response(struct http_request *r)
watch(&r->alarm); watch(&r->alarm);
} }
/* Start sending a response back to the client. The response's Content-Type is set by the /* Start sending a static (pre-computed) response back to the client. The response's Content-Type
* 'mime_type' parameter (in the standard format "type/subtype"). The response's content is set * is set by the 'mime_type' parameter (in the standard format "type/subtype"). The response's
* from the 'body' and 'bytes' parameters, which need not point to static data, ie, is no longer * content is set from the 'body' and 'bytes' parameters, which need not point to persistent data,
* used once this function returns. * ie, the memory pointed to by 'body' is no longer referenced once this function returns.
* *
* @author Andrew Bettison <andrew@servalproject.com> * @author Andrew Bettison <andrew@servalproject.com>
*/ */
void http_request_response(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes) void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes)
{ {
assert(r->phase == RECEIVE); assert(r->phase == RECEIVE);
assert(result >= 100); assert(result >= 100);
assert(result < 600); assert(result < 300);
assert(mime_type != NULL); assert(mime_type != NULL);
assert(mime_type[0]); assert(mime_type[0]);
r->response.result_code = result; r->response.result_code = result;
@ -1613,6 +1613,20 @@ void http_request_response(struct http_request *r, int result, const char *mime_
http_request_start_response(r); http_request_start_response(r);
} }
void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR generator)
{
assert(r->phase == RECEIVE);
assert(result >= 100);
assert(result < 300);
assert(mime_type != NULL);
assert(mime_type[0]);
r->response.result_code = result;
r->response.header.content_type = mime_type;
r->response.content = NULL;
r->response.content_generator = generator;
http_request_start_response(r);
}
/* Start sending a short redirection or error response back to the client. The result code must be /* Start sending a short redirection or error response back to the client. The result code must be
* either a redirection (3xx) or client error (4xx) or server error (5xx) code. The 'body' argument * either a redirection (3xx) or client error (4xx) or server error (5xx) code. The 'body' argument
* may be a bare message which is enclosed in an HTML envelope to form the response content, so it * may be a bare message which is enclosed in an HTML envelope to form the response content, so it

View File

@ -73,11 +73,13 @@ struct http_response_headers {
const char *boundary; const char *boundary;
}; };
typedef int (*HTTP_CONTENT_GENERATOR)(struct http_request *);
struct http_response { struct http_response {
uint16_t result_code; uint16_t result_code;
struct http_response_headers header; struct http_response_headers header;
const char *content; const char *content;
int (*content_generator)(struct http_request *); // callback to produce more content HTTP_CONTENT_GENERATOR content_generator; // callback to produce more content
}; };
#define MIME_FILENAME_MAXLEN 127 #define MIME_FILENAME_MAXLEN 127
@ -108,7 +110,8 @@ void http_request_init(struct http_request *r, int sockfd);
void http_request_free_response_buffer(struct http_request *r); void http_request_free_response_buffer(struct http_request *r);
int http_request_set_response_bufsize(struct http_request *r, size_t bufsiz); int http_request_set_response_bufsize(struct http_request *r, size_t bufsiz);
void http_request_finalise(struct http_request *r); void http_request_finalise(struct http_request *r);
void http_request_response(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes); void http_request_response_static(struct http_request *r, int result, const char *mime_type, const char *body, uint64_t bytes);
void http_request_response_generated(struct http_request *r, int result, const char *mime_type, HTTP_CONTENT_GENERATOR);
void http_request_simple_response(struct http_request *r, uint16_t result, const char *body); void http_request_simple_response(struct http_request *r, uint16_t result, const char *body);
typedef int (*HTTP_REQUEST_PARSER)(struct http_request *); typedef int (*HTTP_REQUEST_PARSER)(struct http_request *);

View File

@ -160,7 +160,7 @@ int rhizome_direct_enquiry_end(struct http_request *hr)
if (http_request_set_response_bufsize(&r->http, bytes) == -1) if (http_request_set_response_bufsize(&r->http, bytes) == -1)
http_request_simple_response(&r->http, 500, "Internal Error: Out of memory"); http_request_simple_response(&r->http, 500, "Internal Error: Out of memory");
else else
http_request_response(&r->http, 200, "binary/octet-stream", (const char *)c->buffer, bytes); http_request_response_static(&r->http, 200, "binary/octet-stream", (const char *)c->buffer, bytes);
rhizome_direct_bundle_iterator_free(&c); rhizome_direct_bundle_iterator_free(&c);
} else } else
http_request_simple_response(&r->http, 500, "Internal Error: No response to enquiry"); http_request_simple_response(&r->http, 500, "Internal Error: No response to enquiry");
@ -258,7 +258,7 @@ int rhizome_direct_addfile_end(struct http_request *hr)
if (config.debug.rhizome) if (config.debug.rhizome)
DEBUGF("Import sans-manifest appeared to succeed"); DEBUGF("Import sans-manifest appeared to succeed");
/* Respond with the manifest that was added. */ /* Respond with the manifest that was added. */
http_request_response(&r->http, 200, "text/plain", (const char *)m->manifestdata, m->manifest_bytes); http_request_response_static(&r->http, 200, "text/plain", (const char *)m->manifestdata, m->manifest_bytes);
/* clean up after ourselves */ /* clean up after ourselves */
if (mout && mout != m) if (mout && mout != m)
rhizome_manifest_free(mout); rhizome_manifest_free(mout);

View File

@ -331,7 +331,7 @@ static int neighbour_page(rhizome_http_request *r, const char *remainder)
strbuf_puts(b, "</body></html>"); strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)) if (strbuf_overrun(b))
return -1; return -1;
http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b));
return 0; return 0;
} }
@ -351,7 +351,7 @@ static int interface_page(rhizome_http_request *r, const char *remainder)
strbuf_puts(b, "</body></html>"); strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)) if (strbuf_overrun(b))
return -1; return -1;
http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b));
return 0; return 0;
} }
@ -374,7 +374,7 @@ static int rhizome_status_page(rhizome_http_request *r, const char *remainder)
strbuf_puts(b, "</body></html>"); strbuf_puts(b, "</body></html>");
if (strbuf_overrun(b)) if (strbuf_overrun(b))
return -1; return -1;
http_request_response(&r->http, 200, "text/html", buf, strbuf_len(b)); http_request_response_static(&r->http, 200, "text/html", buf, strbuf_len(b));
return 0; return 0;
} }
@ -455,8 +455,7 @@ static int rhizome_file_page(rhizome_http_request *r, const char *remainder)
r->http.response.header.resource_length = closed.last; r->http.response.header.resource_length = closed.last;
r->http.response.header.content_length = closed.last - closed.first; r->http.response.header.content_length = closed.last - closed.first;
r->read_state.offset = closed.first; r->read_state.offset = closed.first;
r->http.response.content_generator = rhizome_file_content; http_request_response_generated(&r->http, result_code, "application/binary", rhizome_file_content);
http_request_response(&r->http, result_code, "application/binary", NULL, 0);
return 0; return 0;
} }
@ -478,7 +477,7 @@ static int manifest_by_prefix_page(rhizome_http_request *r, const char *remainde
if (ret == -1) if (ret == -1)
http_request_simple_response(&r->http, 500, NULL); http_request_simple_response(&r->http, 500, NULL);
else if (ret == 0) else if (ret == 0)
http_request_response(&r->http, 200, "application/binary", (const char *)m->manifestdata, m->manifest_all_bytes); http_request_response_static(&r->http, 200, "application/binary", (const char *)m->manifestdata, m->manifest_all_bytes);
rhizome_manifest_free(m); rhizome_manifest_free(m);
return ret <= 0 ? 0 : 1; return ret <= 0 ? 0 : 1;
} }
@ -487,7 +486,7 @@ static int fav_icon_header(rhizome_http_request *r, const char *remainder)
{ {
if (*remainder) if (*remainder)
return 1; return 1;
http_request_response(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len); http_request_response_static(&r->http, 200, "image/vnd.microsoft.icon", (const char *)favicon_bytes, favicon_len);
return 0; return 0;
} }
@ -521,6 +520,6 @@ static int root_page(rhizome_http_request *r, const char *remainder)
WHY("HTTP Root page buffer overrun"); WHY("HTTP Root page buffer overrun");
http_request_simple_response(&r->http, 500, NULL); http_request_simple_response(&r->http, 500, NULL);
} else } else
http_request_response(&r->http, 200, "text/html", temp, strbuf_len(b)); http_request_response_static(&r->http, 200, "text/html", temp, strbuf_len(b));
return 0; return 0;
} }