Compare commits
No commits in common. "c9c21105f63e4ed385a38c6d39dae657d4535316" and "0196588f515c8844326199733be3ff2b8a71a26c" have entirely different histories.
c9c21105f6
...
0196588f51
4 changed files with 13 additions and 127 deletions
|
@ -36,5 +36,3 @@ Var='''Test var value'''
|
|||
PATH=/inner
|
||||
HTML_FILE='''example_config/inner.html'''
|
||||
VAR_FILE='''example_config/var.html'''
|
||||
|
||||
PATH=/error
|
||||
|
|
81
src/http.c
81
src/http.c
|
@ -32,32 +32,11 @@
|
|||
#define REQUEST_PATH_BUFFER_SIZE 256
|
||||
#define REQUEST_PROTO_BUFFER_SIZE 16
|
||||
|
||||
const char *c_simple_http_response_code_error_to_response(
|
||||
enum C_SIMPLE_HTTP_ResponseCode response_code) {
|
||||
switch (response_code) {
|
||||
case C_SIMPLE_HTTP_Response_400_Bad_Request:
|
||||
return "HTTP/1.1 400 Bad Request\nAllow: GET\nContent-Type: text/html\n"
|
||||
"Content-Length: 25\n\n"
|
||||
"<h1>400 Bad Request</h1>\n";
|
||||
case C_SIMPLE_HTTP_Response_404_Not_Found:
|
||||
return "HTTP/1.1 404 Not Found\nAllow: GET\nContent-Type: text/html\n"
|
||||
"Content-Length: 23\n\n"
|
||||
"<h1>404 Not Found</h1>\n";
|
||||
case C_SIMPLE_HTTP_Response_500_Internal_Server_Error:
|
||||
default:
|
||||
return "HTTP/1.1 500 Internal Server Error\nAllow: GET\n"
|
||||
"Content-Type: text/html\n"
|
||||
"Content-Length: 35\n\n"
|
||||
"<h1>500 Internal Server Error</h1>\n";
|
||||
}
|
||||
}
|
||||
|
||||
char *c_simple_http_request_response(
|
||||
const char *request,
|
||||
unsigned int size,
|
||||
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||
size_t *out_size,
|
||||
enum C_SIMPLE_HTTP_ResponseCode *out_response_code) {
|
||||
size_t *out_size) {
|
||||
if (out_size) {
|
||||
*out_size = 0;
|
||||
}
|
||||
|
@ -75,9 +54,6 @@ char *c_simple_http_request_response(
|
|||
request_type[request_type_idx++] = request[idx];
|
||||
}
|
||||
if (request_type_idx == 0) {
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_400_Bad_Request;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
|
@ -103,9 +79,6 @@ char *c_simple_http_request_response(
|
|||
request_path[request_path_idx++] = request[idx];
|
||||
}
|
||||
if (request_path_idx == 0) {
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_400_Bad_Request;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
|
@ -131,9 +104,6 @@ char *c_simple_http_request_response(
|
|||
request_proto[request_proto_idx++] = request[idx];
|
||||
}
|
||||
if (request_proto_idx == 0) {
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_400_Bad_Request;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
|
@ -142,71 +112,24 @@ char *c_simple_http_request_response(
|
|||
|
||||
if (strcmp(request_type, "GET") != 0) {
|
||||
fprintf(stderr, "ERROR Only GET requests are allowed!\n");
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_400_Bad_Request;
|
||||
}
|
||||
return NULL;
|
||||
} else if (strcmp(request_proto, "HTTP/1.1") != 0) {
|
||||
fprintf(stderr, "ERROR Only HTTP/1.1 protocol requests are allowed!\n");
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_400_Bad_Request;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t generated_size = 0;
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *stripped_path = c_simple_http_strip_path(
|
||||
request_path, request_path_idx);
|
||||
char *generated_buf = c_simple_http_path_to_generated(
|
||||
stripped_path ? stripped_path : request_path,
|
||||
request_path,
|
||||
templates,
|
||||
&generated_size);
|
||||
|
||||
if (!generated_buf || generated_size == 0) {
|
||||
fprintf(stderr, "ERROR Unable to generate response html for path \"%s\"!\n",
|
||||
request_path);
|
||||
if (out_response_code) {
|
||||
if (
|
||||
simple_archiver_hash_map_get(
|
||||
templates->hash_map,
|
||||
stripped_path ? stripped_path : request_path,
|
||||
stripped_path ? strlen(stripped_path) + 1 : request_path_idx + 1)
|
||||
== NULL) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_404_Not_Found;
|
||||
} else {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_500_Internal_Server_Error;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (out_size) {
|
||||
*out_size = generated_size;
|
||||
}
|
||||
if (out_response_code) {
|
||||
*out_response_code = C_SIMPLE_HTTP_Response_200_OK;
|
||||
}
|
||||
return generated_buf;
|
||||
}
|
||||
|
||||
char *c_simple_http_strip_path(const char *path, size_t path_size) {
|
||||
size_t idx = 0;
|
||||
for (; idx < path_size && path[idx] != 0; ++idx) {
|
||||
if (path[idx] == '?' || path[idx] == '#') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx >= path_size || path[idx] == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *stripped_path = malloc(idx + 1);
|
||||
memcpy(stripped_path, path, idx);
|
||||
stripped_path[idx] = 0;
|
||||
|
||||
return stripped_path;
|
||||
}
|
||||
|
||||
// vim: ts=2 sts=2 sw=2
|
||||
|
|
21
src/http.h
21
src/http.h
|
@ -28,34 +28,15 @@
|
|||
|
||||
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HTTPTemplates;
|
||||
|
||||
enum C_SIMPLE_HTTP_ResponseCode {
|
||||
C_SIMPLE_HTTP_Response_200_OK,
|
||||
C_SIMPLE_HTTP_Response_400_Bad_Request,
|
||||
C_SIMPLE_HTTP_Response_404_Not_Found,
|
||||
C_SIMPLE_HTTP_Response_500_Internal_Server_Error,
|
||||
};
|
||||
|
||||
// If the response code is an error, returns a full response string that doesn't
|
||||
// need to be free'd. Otherwise, returns as if error 500.
|
||||
const char *c_simple_http_response_code_error_to_response(
|
||||
enum C_SIMPLE_HTTP_ResponseCode response_code);
|
||||
|
||||
/// Returned buffer must be "free"d after use.
|
||||
/// If the request is not valid, or 404, then the buffer will be NULL.
|
||||
char *c_simple_http_request_response(
|
||||
const char *request,
|
||||
unsigned int size,
|
||||
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||
size_t *out_size,
|
||||
enum C_SIMPLE_HTTP_ResponseCode *out_response_code
|
||||
size_t *out_size
|
||||
);
|
||||
|
||||
/// Takes a PATH string and returns a "bare" path.
|
||||
/// This will simply omit the first instance of "?" or "#" and the rest of the
|
||||
/// string.
|
||||
/// Must be free'd if returns non-NULL.
|
||||
char *c_simple_http_strip_path(const char *path, size_t path_size);
|
||||
|
||||
#endif
|
||||
|
||||
// vim: ts=2 sts=2 sw=2
|
||||
|
|
34
src/main.c
34
src/main.c
|
@ -141,18 +141,12 @@ int main(int argc, char **argv) {
|
|||
puts("");
|
||||
|
||||
size_t response_size = 0;
|
||||
enum C_SIMPLE_HTTP_ResponseCode response_code;
|
||||
const char *response = c_simple_http_request_response(
|
||||
(const char*)recv_buf,
|
||||
(unsigned int)read_ret,
|
||||
&parsed_config,
|
||||
&response_size,
|
||||
&response_code);
|
||||
if (response && response_code == C_SIMPLE_HTTP_Response_200_OK) {
|
||||
(const char*)recv_buf, (unsigned int)read_ret, &parsed_config, &response_size);
|
||||
if (response) {
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "HTTP/1.1 200 OK\n", 16));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Allow: GET\n", 11));
|
||||
CHECK_ERROR_WRITE(write(
|
||||
connection_fd, "Content-Type: text/html\n", 24));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Content-Type: text/html\n", 24));
|
||||
char content_length_buf[128];
|
||||
size_t content_length_buf_size = 0;
|
||||
memcpy(content_length_buf, "Content-Length: ", 16);
|
||||
|
@ -172,28 +166,18 @@ int main(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
content_length_buf_size += (size_t)written;
|
||||
CHECK_ERROR_WRITE(write(
|
||||
connection_fd, content_length_buf, content_length_buf_size));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, content_length_buf, content_length_buf_size));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "\n", 1));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, response, response_size));
|
||||
|
||||
free((void*)response);
|
||||
} else {
|
||||
const char *response = c_simple_http_response_code_error_to_response(
|
||||
response_code);
|
||||
size_t response_size = strlen(response);
|
||||
if (response) {
|
||||
CHECK_ERROR_WRITE(write(connection_fd, response, response_size));
|
||||
} else {
|
||||
CHECK_ERROR_WRITE(write(
|
||||
connection_fd, "HTTP/1.1 404 Not Found\n", 23));
|
||||
// TODO handle internal errors also.
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "HTTP/1.1 404 Not Found\n", 23));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Allow: GET\n", 11));
|
||||
CHECK_ERROR_WRITE(write(
|
||||
connection_fd, "Content-Type: text/html\n", 24));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Content-Length: 35\n", 19));
|
||||
CHECK_ERROR_WRITE(write(
|
||||
connection_fd, "\n<h1>500 Internal Server Error</h1>\n", 36));
|
||||
}
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Content-Type: text/html\n", 24));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "Content-Length: 14\n", 19));
|
||||
CHECK_ERROR_WRITE(write(connection_fd, "\n404 Not Found\n", 15));
|
||||
}
|
||||
close(connection_fd);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue