diff options
author | cflip <cflip@cflip.net> | 2023-05-27 11:50:37 -0600 |
---|---|---|
committer | cflip <cflip@cflip.net> | 2023-05-27 11:50:37 -0600 |
commit | 30458088f0f6acbb9581fecd2aa39d97c13d7373 (patch) | |
tree | 71ee8fc561a3ee3be1e674cdb9db1c3a600080f6 | |
parent | 7f1d6bbc335288df1e24e7c8f305c32afe6b050a (diff) |
Load and serve files from the filesystem
-rw-r--r-- | cfws.c | 66 | ||||
-rw-r--r-- | http.c | 5 | ||||
-rw-r--r-- | http.h | 5 |
3 files changed, 64 insertions, 12 deletions
@@ -1,4 +1,6 @@ #include <arpa/inet.h> +#include <errno.h> +#include <linux/limits.h> #include <netdb.h> #include <signal.h> #include <stdio.h> @@ -6,6 +8,7 @@ #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> @@ -17,6 +20,8 @@ #define CFWS_DEFAULT_PORT 8080 +size_t file_read(const char *, char **); + int initialize_server(int); void handle_connection(); @@ -41,6 +46,44 @@ int main(int argc, char *argv[]) return 0; } +size_t file_read(const char *uri_path, char **buffer) +{ + FILE *fp; + struct stat statbuf; + char path[PATH_MAX]; + long len; + + /* Prepend the current working directory to the uri path */ + getcwd(path, PATH_MAX); + strncat(path, uri_path, PATH_MAX - 1); + + /* Append 'index.html' to directory paths. */ + stat(path, &statbuf); + if (S_ISDIR(statbuf.st_mode)) + strcat(path, "index.html"); + + fp = fopen(path, "rb"); + if (fp == NULL) { + /* + * File not found is a very common and harmless error, so + * there's no need to print it out every time. + */ + if (errno != ENOENT) + perror("Failed to open file"); + return 0; + } + + fseek(fp, 0, SEEK_END); + len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + *buffer = malloc(len); + fread(*buffer, 1, len, fp); + + fclose(fp); + return len; +} + int initialize_server(int port) { struct sockaddr_in addr; @@ -81,8 +124,10 @@ int initialize_server(int port) void handle_connection(int connfd) { - char msgbuf[128]; - char *resbuf; + char *content_buf; + size_t content_len, response_len; + + char resbuf[CFWS_MAX_RESPONSE]; char readbuf[CFWS_MAXREAD]; struct http_request req; @@ -91,12 +136,17 @@ void handle_connection(int connfd) req = http_parse_request(readbuf); - snprintf(msgbuf, 128, "Welcome to %s", req.uri); - - http_build_response(&resbuf, HTTP_RESPONSE_OK, msgbuf); - write(connfd, resbuf, strlen(resbuf)); + content_len = file_read(req.uri, &content_buf); + if (content_len == 0) { + const char *msg = "Could not find the specified file."; + response_len = http_build_response(resbuf, + HTTP_RESPONSE_NOTFOUND, msg, strlen(msg)); + } else { + response_len = http_build_response(resbuf, HTTP_RESPONSE_OK, + content_buf, content_len); + free(content_buf); + } - free(resbuf); + write(connfd, resbuf, response_len); http_free_request(&req); } - @@ -30,8 +30,7 @@ void http_free_request(struct http_request *req) free(req->uri); } -void http_build_response(char **res, enum http_res_code code, const char *msg) +int http_build_response(char *res, enum http_res_code code, const char *msg, size_t msglen) { - *res = malloc(128); - sprintf(*res, "HTTP/1.1 200 OK\r\n\r\n%s\r\n", msg); + return snprintf(res, CFWS_MAX_RESPONSE, "HTTP/1.1 200 OK\r\n\r\n%.*s\r\n", msglen, msg); } @@ -1,7 +1,10 @@ #ifndef _H_HTTP #define _H_HTTP +#include <stddef.h> + #define CFWS_MAXURI 128 +#define CFWS_MAX_RESPONSE 4096 enum http_req_method { HTTP_METHOD_GET @@ -20,6 +23,6 @@ struct http_request { struct http_request http_parse_request(const char *); void http_free_request(struct http_request *); -void http_build_response(char **, enum http_res_code, const char *); +int http_build_response(char *, enum http_res_code, const char *, size_t); #endif |