chore: complete HTTP cleanup

main
Sean McBride 5 years ago
parent 4a80e6dd70
commit 1f988bd113

@ -9,12 +9,7 @@
/* all in-memory ptrs.. don't mess around with that! */ /* all in-memory ptrs.. don't mess around with that! */
struct http_header { struct http_header {
char *key; char *key;
char *val; char *value;
};
struct http_response_header {
char *header;
int length;
}; };
struct http_request { struct http_request {
@ -22,12 +17,18 @@ struct http_request {
int header_count; int header_count;
char * body; char * body;
int body_length; int body_length;
// TODO: What does bodyrlen mean? Does this suggest that I've misunderstood what bodylen was? // TODO: What does bodyrlen mean? Does this suggest that I've misunderstood what body_length is?
int bodyrlen; int bodyrlen;
// additional for http-parser // additional for http-parser
int last_was_value; int last_was_value; // http-parser flag used to help the http-parser callbacks differentiate between header fields and values to know when to allocate a new header
int header_end; int header_end; // boolean flag set when header processing is complete
int message_begin, message_end; int message_begin; // boolean flag set when body processing begins
int message_end; // boolean flag set when body processing is complete
};
struct http_response_header {
char *header;
int length;
}; };
struct http_response { struct http_response {

@ -2,19 +2,15 @@
#define SRFT_HTTP_API_H #define SRFT_HTTP_API_H
#include <http.h> #include <http.h>
int http_request_body_get_sb(struct sandbox *sandbox, char **body);
int http_request_parse_sb(struct sandbox *sandbox, size_t l);
int http_response_header_set_sb(struct sandbox *sandbox, char *h, int length); /***************************************************
int http_response_body_set_sb(struct sandbox *sandbox, char *body, int length); * General HTTP Request Functions *
int http_response_status_set_sb(struct sandbox *sandbox, char *status, int length); **************************************************/
int http_response_vector_sb(struct sandbox *sandbox); int http_request_body_get_sb(struct sandbox *sandbox, char **body);
void http_init(void);
/** /**
* Gets the request of the body * Gets the HTTP Request body from the current sandbox
* @param body pointer of pointer that we want to set to the http_request's body * @param body pointer that we'll assign to the http_request body
* @returns the length of the http_request's body * @returns the length of the http_request's body
**/ **/
static inline int static inline int
@ -23,6 +19,14 @@ http_request_body_get(char **body)
return http_request_body_get_sb(sandbox_current(), body); return http_request_body_get_sb(sandbox_current(), body);
} }
/***************************************************
* General HTTP Response Functions *
**************************************************/
int http_response_header_set_sb(struct sandbox *sandbox, char *h, int length);
int http_response_body_set_sb(struct sandbox *sandbox, char *body, int length);
int http_response_status_set_sb(struct sandbox *sandbox, char *status, int length);
int http_response_vector_sb(struct sandbox *sandbox);
/** /**
* Set an HTTP Response Header on the current sandbox * Set an HTTP Response Header on the current sandbox
* @param header string of the header that we want to set * @param header string of the header that we want to set
@ -60,8 +64,8 @@ http_response_status_set(char *status, int length)
} }
/** /**
* ??? on the current sandbox * Encode the current sandbox's HTTP Response as an array of buffers
* @returns ??? * @returns the number of buffers used to store the HTTP Response
**/ **/
static inline int static inline int
http_response_vector(void) http_response_vector(void)
@ -69,9 +73,15 @@ http_response_vector(void)
return http_response_vector_sb(sandbox_current()); return http_response_vector_sb(sandbox_current());
} }
/***********************************************************************
* http-parser Setup and Excute *
**********************************************************************/
void http_init(void);
int http_request_parse_sb(struct sandbox *sandbox, size_t l);
/** /**
* ??? * Parse the current sandbox's req_resp_data up to length
* @param length ???? * @param length
* @returns 0 * @returns 0
**/ **/
static inline int static inline int

@ -5,135 +5,9 @@
http_parser_settings settings; http_parser_settings settings;
/** /***************************************************
* Sets the HTTP Request's message_begin and last_was_value flags to true * General HTTP Request Functions *
* @param parser **************************************************/
**/
static inline int
http_on_msg_begin(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->message_begin = 1;
http_request->last_was_value = 1; // should always start with a header..
return 0;
}
/**
* Sets the HTTP Request's message_end flag to true
* @param parser
**/
static inline int
http_on_msg_end(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->message_end = 1;
return 0;
}
/**
* Sets the HTTP Request's header_end flag to true
* @param parser
**/
static inline int
http_on_header_end(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->header_end = 1;
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_url(http_parser *parser, const char *at, size_t length)
{
struct sandbox *sandbox = parser->data;
assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0);
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_header_field(http_parser *parser, const char *at, size_t length)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
if (http_request->last_was_value) http_request->header_count++;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADER_MAXSZ);
http_request->last_was_value = 0;
http_request->headers[http_request->header_count - 1].key = (char *)
at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_header_value(http_parser *parser, const char *at, size_t length)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->last_was_value = 1;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADERVAL_MAXSZ);
http_request->headers[http_request->header_count - 1].val = (char *)
at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* ???
* @param parser
* @param at
* @param length
* @returns 0
**/
static inline int
http_on_body(http_parser *parser, const char *at, size_t length)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
assert(http_request->body_length + length <= sandbox->module->max_request_size);
if (!http_request->body)
http_request->body = (char *)at;
else
assert(http_request->body + http_request->body_length == at);
http_request->body_length += length;
return 0;
}
/** /**
* Gets the HTTP Request body from a Sandbox * Gets the HTTP Request body from a Sandbox
@ -150,10 +24,14 @@ http_request_body_get_sb(struct sandbox *sandbox, char **body)
return http_request->body_length; return http_request->body_length;
} }
/***************************************************
* General HTTP Response Functions *
**************************************************/
/** /**
* Set an HTTP Response Header on a Sandbox * Append a header to the HTTP Response of a Sandbox
* @param sandbox the sandbox we want to set the request header on * @param sandbox the sandbox we want to set the request header on
* @param header string of the header that we want to set * @param header string containing the header that we want to append
* @param length the length of the header string * @param length the length of the header string
* @returns 0 (abends program in case of error) * @returns 0 (abends program in case of error)
**/ **/
@ -209,85 +87,230 @@ http_response_status_set_sb(struct sandbox *sandbox, char *status, int length)
} }
/** /**
* ??? * Encodes a sandbox's HTTP Response as an array of buffers
* @param sandbox the sandbox we want to set the request status on * @param sandbox the sandbox containing the HTTP response we want to encode as buffers
* @returns ??? * @returns the number of buffers used to store the HTTP Response
**/ **/
int int
http_response_vector_sb(struct sandbox *sandbox) http_response_vector_sb(struct sandbox *sandbox)
{ {
int nb = 0; int buffer_count = 0;
struct http_response *http_response = &sandbox->http_response; struct http_response *http_response = &sandbox->http_response;
#ifdef USE_HTTP_UVIO #ifdef USE_HTTP_UVIO
http_response->bufs[nb] = uv_buf_init(http_response->status, http_response->status_length); http_response->bufs[buffer_count] = uv_buf_init(http_response->status, http_response->status_length);
nb++; buffer_count++;
for (int i = 0; i < http_response->header_count; i++) { for (int i = 0; i < http_response->header_count; i++) {
http_response->bufs[nb] = uv_buf_init(http_response->headers[i].header, http_response->bufs[buffer_count] = uv_buf_init(http_response->headers[i].header, http_response->headers[i].length);
http_response->headers[i].length); buffer_count++;
nb++;
} }
if (http_response->body) { if (http_response->body) {
http_response->bufs[nb] = uv_buf_init(http_response->body, http_response->body_length); http_response->bufs[buffer_count] = uv_buf_init(http_response->body, http_response->body_length);
nb++; buffer_count++;
http_response->bufs[nb] = uv_buf_init(http_response->status + http_response->status_length - 2, http_response->bufs[buffer_count] = uv_buf_init(http_response->status + http_response->status_length - 2, 2); // for crlf
2); // for crlf buffer_count++;
nb++;
} }
#else #else
http_response->bufs[nb].iov_base = http_response->status; http_response->bufs[buffer_count].iov_base = http_response->status;
http_response->bufs[nb].iov_len = http_response->status_length; http_response->bufs[buffer_count].iov_len = http_response->status_length;
nb++; buffer_count++;
for (int i = 0; i < http_response->header_count; i++) { for (int i = 0; i < http_response->header_count; i++) {
http_response->bufs[nb].iov_base = http_response->headers[i].header; http_response->bufs[buffer_count].iov_base = http_response->headers[i].hdr;
http_response->bufs[nb].iov_len = http_response->headers[i].length; http_response->bufs[buffer_count].iov_len = http_response->headers[i].len;
nb++; buffer_count++;
} }
if (http_response->body) { if (http_response->body) {
http_response->bufs[nb].iov_base = http_response->body; http_response->bufs[buffer_count].iov_base = http_response->body;
http_response->bufs[nb].iov_len = http_response->body_length; http_response->bufs[buffer_count].iov_len = http_response->body_length;
nb++; buffer_count++;
http_response->bufs[nb].iov_base = http_response->status + http_response->status_length - 2; http_response->bufs[buffer_count].iov_base = http_response->status + http_response->status_length - 2;
http_response->bufs[nb].iov_len = 2; http_response->bufs[buffer_count].iov_len = 2;
nb++; buffer_count++;
} }
#endif #endif
return nb; return buffer_count;
} }
/***********************************************************************
* http-parser Callbacks in lifecycle order *
**********************************************************************/
/** /**
* ??? * http-parser data callback called when a URL is called
* @param sandbox the sandbox we want to set the request status on * Sanity check to make sure that the path matches the name of the module
* TODO: Why does this not fail this assertion? To execute fibonacci, I just request localhost:10000, not localhost:10000/fibonacci
* @param parser
* @param at the start of the URL
* @param length the length of the URL
* @returns 0
**/
static inline int
http_on_url(http_parser *parser, const char *at, size_t length)
{
struct sandbox *sandbox = parser->data;
assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0);
return 0;
}
/**
* http-parser callback called when parsing of a new message begins
* Sets the HTTP Request's message_begin and last_was_value flags to true
* @param parser
**/
static inline int
http_on_msg_begin(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->message_begin = 1;
http_request->last_was_value = 1; // should always start with a header..
return 0;
}
/**
* http-parser callback called when a header field is parsed
* Sets the key value of the latest header
* on a new header if last_was_value is true
* updating an existing header if last_was_value is false
* TODO: Is this logic correct? What is the relationship between fields and values? Is overwrite the correct logic if on_header executes twice in a row?
* @param parser
* @param at start address of the header field
* @param length length of the header field
* @returns 0
**/
static inline int
http_on_header_field(http_parser *parser, const char *at, size_t length)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
if (http_request->last_was_value) http_request->header_count++;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADER_MAXSZ);
http_request->last_was_value = 0;
http_request->headers[http_request->header_count - 1].key = (char *)at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* http-parser callback called when a header value is parsed
* Writes the value to the latest header and sets last_was_value to true
* @param parser
* @param at start address of the header value
* @param length length of the header value
* @returns 0
**/
static inline int
http_on_header_value(http_parser *parser, const char *at, size_t length)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->last_was_value = 1;
assert(http_request->header_count <= HTTP_HEADERS_MAX);
assert(length < HTTP_HEADERVAL_MAXSZ);
http_request->headers[http_request->header_count - 1].value = (char *)at; // it is from the sandbox's req_resp_data, should persist.
return 0;
}
/**
* http-parser callback called when header parsing is complete
* Just sets the HTTP Request's header_end flag to true
* @param parser
**/
static inline int
http_on_header_end(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->header_end = 1;
return 0;
}
/**
* http-parser callback called for HTTP Bodies
* Assigns the parsed data to the http_request body of the sandbox struct
* @param parser
* @param at
* @param length * @param length
* @returns 0 * @returns 0
*
* Global State: settings
**/ **/
int static inline int
http_request_parse_sb(struct sandbox *sandbox, size_t length) http_on_body(http_parser *parser, const char *at, size_t length)
{ {
http_parser_execute(&sandbox->http_parser, &settings, sandbox->req_resp_data + sandbox->rr_data_len, length); struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
assert(http_request->body_length + length <= sandbox->module->max_request_size);
if (!http_request->body)
http_request->body = (char *)at;
else
assert(http_request->body + http_request->body_length == at);
http_request->body_length += length;
return 0;
}
/**
* Sets the HTTP Request's message_end flag to true
* @param parser
**/
static inline int
http_on_msg_end(http_parser *parser)
{
struct sandbox * sandbox = parser->data;
struct http_request *http_request = &sandbox->http_request;
http_request->message_end = 1;
return 0; return 0;
} }
/***********************************************************************
* http-parser Setup and Excute *
**********************************************************************/
/** /**
* Configure Callback Functions for HTTP Events * The settings global with the Callback Functions for HTTP Events
*/ */
void void
http_init(void) http_init(void)
{ {
http_parser_settings_init(&settings); http_parser_settings_init(&settings);
settings.on_url = http_on_url; settings.on_url = http_on_url;
settings.on_message_begin = http_on_msg_begin;
settings.on_header_field = http_on_header_field; settings.on_header_field = http_on_header_field;
settings.on_header_value = http_on_header_value; settings.on_header_value = http_on_header_value;
settings.on_body = http_on_body;
settings.on_headers_complete = http_on_header_end; settings.on_headers_complete = http_on_header_end;
settings.on_message_begin = http_on_msg_begin; settings.on_body = http_on_body;
settings.on_message_complete = http_on_msg_end; settings.on_message_complete = http_on_msg_end;
} }
/**
* Run the http-parser on the sandbox's req_resp_data using the configured settings global
* @param sandbox the sandbox containing the req_resp data that we want to parse
* @param length The size of the req_resp_data that we want to parse
* @returns 0
*
* Global State: settings
**/
int
http_request_parse_sb(struct sandbox *sandbox, size_t length)
{
// TODO: Why is our start address sandbox->req_resp_data + sandbox->rr_data_len?
http_parser_execute(&sandbox->http_parser, &settings, sandbox->req_resp_data + sandbox->rr_data_len, length);
return 0;
}

Loading…
Cancel
Save