Impl. handling HTTP/1.1 requests
TODO: Handle errors other than 404 Not Found.
This commit is contained in:
parent
3f70c52551
commit
9be6ac32bf
6 changed files with 91 additions and 7 deletions
6
example_config/example.config
Normal file
6
example_config/example.config
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
PATH=/
|
||||||
|
HTML='''Test HTML
|
||||||
|
{{{Var}}}
|
||||||
|
'''
|
||||||
|
|
||||||
|
Var='''Test var value'''
|
|
@ -24,6 +24,7 @@
|
||||||
void print_usage(void) {
|
void print_usage(void) {
|
||||||
puts("Usage:");
|
puts("Usage:");
|
||||||
puts(" -p <port> | --port <port>");
|
puts(" -p <port> | --port <port>");
|
||||||
|
puts(" --config=<config_file>");
|
||||||
}
|
}
|
||||||
|
|
||||||
Args parse_args(int argc, char **argv) {
|
Args parse_args(int argc, char **argv) {
|
||||||
|
@ -42,6 +43,8 @@ Args parse_args(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
|
} else if (strncmp(argv[0], "--config=", 9) == 0 && strlen(argv[0]) > 9) {
|
||||||
|
args.config_file = argv[0] + 9;
|
||||||
} else {
|
} else {
|
||||||
puts("ERROR: Invalid args!\n");
|
puts("ERROR: Invalid args!\n");
|
||||||
print_usage();
|
print_usage();
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
typedef struct Args {
|
typedef struct Args {
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
// Does not need to be free'd, this should point to a string in argv.
|
||||||
|
const char *config_file;
|
||||||
} Args;
|
} Args;
|
||||||
|
|
||||||
void print_usage(void);
|
void print_usage(void);
|
||||||
|
|
30
src/http.c
30
src/http.c
|
@ -21,8 +21,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Third party includes.
|
||||||
|
#include <SimpleArchiver/src/helpers.h>
|
||||||
|
|
||||||
// Local includes
|
// Local includes
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "http_template.h"
|
||||||
|
|
||||||
#define REQUEST_TYPE_BUFFER_SIZE 16
|
#define REQUEST_TYPE_BUFFER_SIZE 16
|
||||||
#define REQUEST_PATH_BUFFER_SIZE 256
|
#define REQUEST_PATH_BUFFER_SIZE 256
|
||||||
|
@ -31,7 +35,11 @@
|
||||||
char *c_simple_http_request_response(
|
char *c_simple_http_request_response(
|
||||||
const char *request,
|
const char *request,
|
||||||
unsigned int size,
|
unsigned int size,
|
||||||
const C_SIMPLE_HTTP_HTTPTemplates *templates) {
|
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||||
|
size_t *out_size) {
|
||||||
|
if (out_size) {
|
||||||
|
*out_size = 0;
|
||||||
|
}
|
||||||
// parse first line.
|
// parse first line.
|
||||||
unsigned int idx = 0;
|
unsigned int idx = 0;
|
||||||
char request_type[REQUEST_TYPE_BUFFER_SIZE] = {0};
|
char request_type[REQUEST_TYPE_BUFFER_SIZE] = {0};
|
||||||
|
@ -102,8 +110,26 @@ char *c_simple_http_request_response(
|
||||||
fprintf(stderr, "Parsing request: got http protocol \"%s\"\n", request_proto);
|
fprintf(stderr, "Parsing request: got http protocol \"%s\"\n", request_proto);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO
|
if (strcmp(request_type, "GET") != 0) {
|
||||||
|
fprintf(stderr, "ERROR Only GET requests are allowed!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t generated_size = 0;
|
||||||
|
char *generated_buf = c_simple_http_path_to_generated(
|
||||||
|
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);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_size) {
|
||||||
|
*out_size = generated_size;
|
||||||
|
}
|
||||||
|
return generated_buf;
|
||||||
|
}
|
||||||
|
|
||||||
// vim: ts=2 sts=2 sw=2
|
// vim: ts=2 sts=2 sw=2
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
|
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
|
||||||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
|
#define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
|
||||||
|
|
||||||
|
// Standard library includes.
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
// Third party includes.
|
// Third party includes.
|
||||||
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
||||||
|
|
||||||
|
@ -30,7 +33,8 @@ typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HTTPTemplates;
|
||||||
char *c_simple_http_request_response(
|
char *c_simple_http_request_response(
|
||||||
const char *request,
|
const char *request,
|
||||||
unsigned int size,
|
unsigned int size,
|
||||||
const C_SIMPLE_HTTP_HTTPTemplates *templates
|
const C_SIMPLE_HTTP_HTTPTemplates *templates,
|
||||||
|
size_t *out_size
|
||||||
);
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
49
src/main.c
49
src/main.c
|
@ -27,6 +27,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
// Third party includes.
|
||||||
|
#include <SimpleArchiver/src/helpers.h>
|
||||||
|
|
||||||
// Local includes.
|
// Local includes.
|
||||||
#include "arg_parse.h"
|
#include "arg_parse.h"
|
||||||
#include "big_endian.h"
|
#include "big_endian.h"
|
||||||
|
@ -39,7 +42,21 @@
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
Args args = parse_args(argc, argv);
|
Args args = parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (!args.config_file) {
|
||||||
|
fprintf(stderr, "ERROR Config file not specified!\n");
|
||||||
|
print_usage();
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
printf("%u\n", args.port);
|
printf("%u\n", args.port);
|
||||||
|
printf("config file is: %s\n", args.config_file);
|
||||||
|
|
||||||
|
__attribute__((cleanup(c_simple_http_clean_up_parsed_config)))
|
||||||
|
C_SIMPLE_HTTP_ParsedConfig parsed_config = c_simple_http_parse_config(
|
||||||
|
args.config_file,
|
||||||
|
"PATH",
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
__attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket =
|
__attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket =
|
||||||
create_tcp_socket(args.port);
|
create_tcp_socket(args.port);
|
||||||
|
@ -95,12 +112,38 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
puts("");
|
puts("");
|
||||||
// TODO Validate request and send response.
|
|
||||||
// TODO WIP
|
size_t response_size = 0;
|
||||||
const char *response = c_simple_http_request_response(
|
const char *response = c_simple_http_request_response(
|
||||||
(const char*)recv_buf, read_ret, NULL);
|
(const char*)recv_buf, read_ret, &parsed_config, &response_size);
|
||||||
if (response) {
|
if (response) {
|
||||||
|
write(connection_fd, "HTTP/1.1 200 OK\n", 16);
|
||||||
|
write(connection_fd, "Allow: GET\n", 11);
|
||||||
|
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);
|
||||||
|
content_length_buf_size = 16;
|
||||||
|
int written = 0;
|
||||||
|
snprintf(
|
||||||
|
content_length_buf + content_length_buf_size,
|
||||||
|
127 - content_length_buf_size,
|
||||||
|
"%lu\n%n",
|
||||||
|
response_size,
|
||||||
|
&written);
|
||||||
|
content_length_buf_size += written;
|
||||||
|
write(connection_fd, content_length_buf, content_length_buf_size);
|
||||||
|
write(connection_fd, "\n", 1);
|
||||||
|
write(connection_fd, response, response_size);
|
||||||
|
|
||||||
free((void*)response);
|
free((void*)response);
|
||||||
|
} else {
|
||||||
|
// TODO handle internal errors also.
|
||||||
|
write(connection_fd, "HTTP/1.1 404 Not Found\n", 23);
|
||||||
|
write(connection_fd, "Allow: GET\n", 11);
|
||||||
|
write(connection_fd, "Content-Type: text/html\n", 24);
|
||||||
|
write(connection_fd, "Content-Length: 14\n", 19);
|
||||||
|
write(connection_fd, "\n404 Not Found\n", 15);
|
||||||
}
|
}
|
||||||
close(connection_fd);
|
close(connection_fd);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue