Added the ability to throw an error
This commit is contained in:
@@ -15,6 +15,7 @@ sitefiles also allow comments with #
|
|||||||
* ```define [variable] [value]``` - sets some global variable
|
* ```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.
|
* ```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.
|
* ```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.
|
##### Other than set, commands should take in a regex as argument 1 and operate on a file specified in argument 2.
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,4 @@
|
|||||||
|
|
||||||
<a href="blog/2022-1-25.html">2021-1-25</a>
|
<a href="blog/2022-1-25.html">2021-1-25</a>
|
||||||
<a href="blog/2022-1-31">2021-1-31</a>
|
<a href="blog/2022-1-31">2021-1-31</a>
|
||||||
|
<a href="blog/forbidden">The forbidden blog post</a>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ define timeout 2000
|
|||||||
set host localhost:8000
|
set host localhost:8000
|
||||||
read / site/index.html
|
read / site/index.html
|
||||||
read /hello site/hello.html
|
read /hello site/hello.html
|
||||||
|
throw /blog/forbidden 403
|
||||||
exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh
|
exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh
|
||||||
read /blog/.* site/blog/
|
read /blog/.* site/blog/
|
||||||
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html
|
#/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html
|
||||||
|
|||||||
@@ -25,9 +25,11 @@
|
|||||||
#define ERROR_404 "404 Not Found"
|
#define ERROR_404 "404 Not Found"
|
||||||
#define ERROR_500 "500 Internal Server Error"
|
#define ERROR_500 "500 Internal Server Error"
|
||||||
|
|
||||||
int sendStringResponse(Connection *conn, char *status, char *str);
|
char *getCode(int code);
|
||||||
int sendBinaryResponse(Connection *conn, char *status, void *data, size_t len);
|
int sendStringResponse(Connection *conn, const char *status, char *str);
|
||||||
int sendErrorResponse(Connection *conn, char *error);
|
int sendBinaryResponse(Connection *conn, const char *status,
|
||||||
|
void *data, size_t len);
|
||||||
|
int sendErrorResponse(Connection *conn, const char *error);
|
||||||
//sendErrorResponse(conn, ERROR_404);
|
//sendErrorResponse(conn, ERROR_404);
|
||||||
int sendHeader(Connection *conn, char *status, size_t len);
|
int sendHeader(Connection *conn, const char *status, size_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
READ,
|
READ,
|
||||||
EXEC,
|
EXEC,
|
||||||
|
THROW,
|
||||||
} Command;
|
} Command;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Stream *acceptStream(Listener *listener, int flags);
|
|||||||
void freeListener(Listener *listener);
|
void freeListener(Listener *listener);
|
||||||
void freeStream(Stream *stream);
|
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);
|
ssize_t recvStream(Stream *stream, void *data, size_t len);
|
||||||
//return value is the same as the read and write syscalls.
|
//return value is the same as the read and write syscalls.
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -30,14 +30,16 @@
|
|||||||
#include <responses.h>
|
#include <responses.h>
|
||||||
#include <responseutil.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.
|
//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) {
|
while (len > 0) {
|
||||||
ssize_t sent = sendStream(stream, buff, len);
|
ssize_t sent = sendStream(stream, data, len);
|
||||||
if (sent < 0)
|
if (sent < 0)
|
||||||
return 1;
|
return 1;
|
||||||
len -= sent;
|
len -= sent;
|
||||||
buff += sent;
|
data += sent;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -142,7 +144,8 @@ static int execResponse(Connection *conn, char *path) {
|
|||||||
close(1);
|
close(1);
|
||||||
close(output[0]);
|
close(output[0]);
|
||||||
dup2(output[1], 1);
|
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) {
|
if (args == NULL) {
|
||||||
close(output[1]);
|
close(output[1]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@@ -239,6 +242,10 @@ int sendResponse(Connection *conn, Sitefile *site) {
|
|||||||
execResponse(conn,
|
execResponse(conn,
|
||||||
site->content[i].arg);
|
site->content[i].arg);
|
||||||
break;
|
break;
|
||||||
|
case THROW:
|
||||||
|
sendErrorResponse(conn,
|
||||||
|
site->content[i].arg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sendErrorResponse(conn, ERROR_500);
|
sendErrorResponse(conn, ERROR_500);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -48,7 +48,24 @@ static int sendConnection(Connection *conn, char *format, ...) {
|
|||||||
return 0;
|
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,
|
return sendConnection(conn,
|
||||||
"HTTP/1.1 %s\r\n"
|
"HTTP/1.1 %s\r\n"
|
||||||
CONST_FIELDS
|
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 =
|
const char *template =
|
||||||
"<meta charset=utf-8>"
|
"<meta charset=utf-8>"
|
||||||
"<h1 text-align=center>"
|
"<h1 text-align=center>"
|
||||||
@@ -73,7 +90,7 @@ int sendErrorResponse(Connection *conn, char *error) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sendBinaryResponse(Connection *conn, char *status,
|
int sendBinaryResponse(Connection *conn, const char *status,
|
||||||
void *data, size_t len) {
|
void *data, size_t len) {
|
||||||
if (sendConnection(conn,
|
if (sendConnection(conn,
|
||||||
"HTTP/1.1 %s\r\n"
|
"HTTP/1.1 %s\r\n"
|
||||||
@@ -86,7 +103,7 @@ int sendBinaryResponse(Connection *conn, char *status,
|
|||||||
return sendStream(conn->stream, data, len) < len;
|
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,
|
return (sendConnection(conn,
|
||||||
"HTTP/1.1 %s\r\n"
|
"HTTP/1.1 %s\r\n"
|
||||||
CONST_FIELDS
|
CONST_FIELDS
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <sitefile.h>
|
#include <sitefile.h>
|
||||||
|
#include <responseutil.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
@@ -156,15 +157,6 @@ error:
|
|||||||
return 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) {
|
Sitefile *parseSitefile(char *path) {
|
||||||
FILE *file = fopen(path, "r");
|
FILE *file = fopen(path, "r");
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
@@ -211,7 +203,7 @@ Sitefile *parseSitefile(char *path) {
|
|||||||
else if (strcmp(argv[1], "host") == 0) {
|
else if (strcmp(argv[1], "host") == 0) {
|
||||||
if (ret->size == lasthostset)
|
if (ret->size == lasthostset)
|
||||||
free(host);
|
free(host);
|
||||||
host = copyString(argv[2]);
|
host = strdup(argv[2]);
|
||||||
lasthostset = ret->size;
|
lasthostset = ret->size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -230,9 +222,9 @@ Sitefile *parseSitefile(char *path) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[1], "key") == 0)
|
else if (strcmp(argv[1], "key") == 0)
|
||||||
ret->key = copyString(argv[2]);
|
ret->key = strdup(argv[2]);
|
||||||
else if (strcmp(argv[1], "cert") == 0)
|
else if (strcmp(argv[1], "cert") == 0)
|
||||||
ret->cert = copyString(argv[2]);
|
ret->cert = strdup(argv[2]);
|
||||||
else if (strcmp(argv[1], "timeout") == 0)
|
else if (strcmp(argv[1], "timeout") == 0)
|
||||||
ret->timeout = atoi(argv[2]);
|
ret->timeout = atoi(argv[2]);
|
||||||
else
|
else
|
||||||
@@ -255,17 +247,23 @@ Sitefile *parseSitefile(char *path) {
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (strcmp(argv[0], "read") == 0) {
|
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)
|
if (ret->content[ret->size].arg == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
ret->content[ret->size].command = READ;
|
ret->content[ret->size].command = READ;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[0], "exec") == 0) {
|
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)
|
if (ret->content[ret->size].arg == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
ret->content[ret->size].command = EXEC;
|
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
|
else
|
||||||
goto error;
|
goto error;
|
||||||
freeTokens(argc, argv);
|
freeTokens(argc, argv);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ void freeStream(Stream *stream) {
|
|||||||
free(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) {
|
switch (stream->type) {
|
||||||
case TCP:
|
case TCP:
|
||||||
return write(stream->fd, data, len);
|
return write(stream->fd, data, len);
|
||||||
|
|||||||
Reference in New Issue
Block a user