Added the ability to throw an error

This commit is contained in:
Nate Choe
2022-02-10 09:30:54 -06:00
parent 8ae835510e
commit e5967f7ead
10 changed files with 56 additions and 28 deletions

View File

@@ -15,6 +15,7 @@ sitefiles also allow comments with #
* ```define [variable] [value]``` - sets some global variable
* ```read [http path] [file path]``` - if the requested path matches ```[http path]```, return the contents of ```[file path]```. If [file path] is a directory, then the http path is appended to [file path] and that is read instead.
* ```exec [http path] [file path]``` - if the requested path matches ```[http path]```, execute ```[file path]``` and send the the contents of stdout. ```argv[0]``` is the ```[file path]```, ```argv[1]``` is a header, ```argv[2]``` is the value for that header, ```argv[3]``` is the next header, and so on.
* ```throw [http path] [error code]``` - If the requested path matches ```[http path]```, send back the http error code ```[error code]```. For standardization purposes, these error codes are just the number.
##### Other than set, commands should take in a regex as argument 1 and operate on a file specified in argument 2.

View File

@@ -4,3 +4,4 @@
<a href="blog/2022-1-25.html">2021-1-25</a>
<a href="blog/2022-1-31">2021-1-31</a>
<a href="blog/forbidden">The forbidden blog post</a>

View File

@@ -6,6 +6,7 @@ define timeout 2000
set host localhost:8000
read / site/index.html
read /hello site/hello.html
throw /blog/forbidden 403
exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh
read /blog/.* site/blog/
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html

View File

@@ -25,9 +25,11 @@
#define ERROR_404 "404 Not Found"
#define ERROR_500 "500 Internal Server Error"
int sendStringResponse(Connection *conn, char *status, char *str);
int sendBinaryResponse(Connection *conn, char *status, void *data, size_t len);
int sendErrorResponse(Connection *conn, char *error);
char *getCode(int code);
int sendStringResponse(Connection *conn, const char *status, char *str);
int sendBinaryResponse(Connection *conn, const char *status,
void *data, size_t len);
int sendErrorResponse(Connection *conn, const char *error);
//sendErrorResponse(conn, ERROR_404);
int sendHeader(Connection *conn, char *status, size_t len);
int sendHeader(Connection *conn, const char *status, size_t len);
#endif

View File

@@ -24,6 +24,7 @@
typedef enum {
READ,
EXEC,
THROW,
} Command;
typedef struct {

View File

@@ -50,7 +50,7 @@ Stream *acceptStream(Listener *listener, int flags);
void freeListener(Listener *listener);
void freeStream(Stream *stream);
ssize_t sendStream(Stream *stream, void *data, size_t len);
ssize_t sendStream(Stream *stream, const void *data, size_t len);
ssize_t recvStream(Stream *stream, void *data, size_t len);
//return value is the same as the read and write syscalls.
#endif

View File

@@ -30,14 +30,16 @@
#include <responses.h>
#include <responseutil.h>
static int resilientSend(Stream *stream, char *buff, size_t len) {
static int resilientSend(Stream *stream, const void *buff, size_t len) {
//Will either write len bytes, or return 1 for error.
const char *data = (const char *) buff;
//using character pointers to do pointer arithmetic
while (len > 0) {
ssize_t sent = sendStream(stream, buff, len);
ssize_t sent = sendStream(stream, data, len);
if (sent < 0)
return 1;
len -= sent;
buff += sent;
data += sent;
}
return 0;
}
@@ -142,7 +144,8 @@ static int execResponse(Connection *conn, char *path) {
close(1);
close(output[0]);
dup2(output[1], 1);
char **args = malloc((conn->fieldCount*2 + 2) * sizeof(char *));
char **args =
malloc((conn->fieldCount*2 + 2) * sizeof(char *));
if (args == NULL) {
close(output[1]);
exit(EXIT_FAILURE);
@@ -239,6 +242,10 @@ int sendResponse(Connection *conn, Sitefile *site) {
execResponse(conn,
site->content[i].arg);
break;
case THROW:
sendErrorResponse(conn,
site->content[i].arg);
break;
default:
sendErrorResponse(conn, ERROR_500);
return 1;

View File

@@ -48,7 +48,24 @@ static int sendConnection(Connection *conn, char *format, ...) {
return 0;
}
int sendStringResponse(Connection *conn, char *status, char *str) {
char *getCode(int code) {
switch (code) {
case 200:
return strdup(CODE_200);
case 400:
return strdup(ERROR_400);
case 403:
return strdup(ERROR_403);
case 404:
return strdup(ERROR_404);
case 500:
return strdup(ERROR_500);
default:
return NULL;
}
}
int sendStringResponse(Connection *conn, const char *status, char *str) {
return sendConnection(conn,
"HTTP/1.1 %s\r\n"
CONST_FIELDS
@@ -59,7 +76,7 @@ int sendStringResponse(Connection *conn, char *status, char *str) {
);
}
int sendErrorResponse(Connection *conn, char *error) {
int sendErrorResponse(Connection *conn, const char *error) {
const char *template =
"<meta charset=utf-8>"
"<h1 text-align=center>"
@@ -73,7 +90,7 @@ int sendErrorResponse(Connection *conn, char *error) {
return ret;
}
int sendBinaryResponse(Connection *conn, char *status,
int sendBinaryResponse(Connection *conn, const char *status,
void *data, size_t len) {
if (sendConnection(conn,
"HTTP/1.1 %s\r\n"
@@ -86,7 +103,7 @@ int sendBinaryResponse(Connection *conn, char *status,
return sendStream(conn->stream, data, len) < len;
}
int sendHeader(Connection *conn, char *status, size_t len) {
int sendHeader(Connection *conn, const char *status, size_t len) {
return (sendConnection(conn,
"HTTP/1.1 %s\r\n"
CONST_FIELDS

View File

@@ -22,6 +22,7 @@
#include <util.h>
#include <sitefile.h>
#include <responseutil.h>
typedef enum {
SUCCESS,
@@ -156,15 +157,6 @@ error:
return ERROR;
}
static char *copyString(char *str) {
size_t len = strlen(str);
char *ret = malloc(len + 1);
if (ret == NULL)
return NULL;
memcpy(ret, str, len + 1);
return ret;
}
Sitefile *parseSitefile(char *path) {
FILE *file = fopen(path, "r");
if (file == NULL)
@@ -211,7 +203,7 @@ Sitefile *parseSitefile(char *path) {
else if (strcmp(argv[1], "host") == 0) {
if (ret->size == lasthostset)
free(host);
host = copyString(argv[2]);
host = strdup(argv[2]);
lasthostset = ret->size;
}
else
@@ -230,9 +222,9 @@ Sitefile *parseSitefile(char *path) {
goto error;
}
else if (strcmp(argv[1], "key") == 0)
ret->key = copyString(argv[2]);
ret->key = strdup(argv[2]);
else if (strcmp(argv[1], "cert") == 0)
ret->cert = copyString(argv[2]);
ret->cert = strdup(argv[2]);
else if (strcmp(argv[1], "timeout") == 0)
ret->timeout = atoi(argv[2]);
else
@@ -255,17 +247,23 @@ Sitefile *parseSitefile(char *path) {
goto error;
if (strcmp(argv[0], "read") == 0) {
ret->content[ret->size].arg = copyString(argv[2]);
ret->content[ret->size].arg = strdup(argv[2]);
if (ret->content[ret->size].arg == NULL)
goto error;
ret->content[ret->size].command = READ;
}
else if (strcmp(argv[0], "exec") == 0) {
ret->content[ret->size].arg = copyString(argv[2]);
ret->content[ret->size].arg = strdup(argv[2]);
if (ret->content[ret->size].arg == NULL)
goto error;
ret->content[ret->size].command = EXEC;
}
else if (strcmp(argv[0], "throw") == 0) {
ret->content[ret->size].arg = getCode(atoi(argv[2]));
if (ret->content[ret->size].arg == NULL)
goto error;
ret->content[ret->size].command = THROW;
}
else
goto error;
freeTokens(argc, argv);

View File

@@ -154,7 +154,7 @@ void freeStream(Stream *stream) {
free(stream);
}
ssize_t sendStream(Stream *stream, void *data, size_t len) {
ssize_t sendStream(Stream *stream, const void *data, size_t len) {
switch (stream->type) {
case TCP:
return write(stream->fd, data, len);