added error response

This commit is contained in:
overflowerror 2021-04-29 23:59:29 +02:00
parent f816772d96
commit 94647efd6e
4 changed files with 79 additions and 22 deletions

23
main.c
View file

@ -13,22 +13,17 @@
struct networkingConfig netConfig; struct networkingConfig netConfig;
static void handler(struct request request, struct response _response) { static void handler(struct request request, struct response _response) {
method_t method = request.metaData.method;
const char* path = request.metaData.path;
const char* queryString = request.metaData.queryString;
//const char* peer = request.peer.addr;
//int port = request.peer.port;
ctx_t ctx = { ctx_t ctx = {
method: method, method: request.metaData.method,
path: path, path: request.metaData.path,
queryString: queryString queryString: request.metaData.queryString,
peerAddr: request.peer.addr,
peerPort: request.peer.port
}; };
response_t response = routerHandler(ctx); response_t response = routerHandler(ctx);
if (response.output == NULL) { if (response.output == NULL) {
response.status = 500; response = errorResponse(500, "route did not provide a reponse handler");
response.headers = headers_create();
} }
int fd = _response.sendHeader(response.status, &response.headers, &request); int fd = _response.sendHeader(response.status, &response.headers, &request);
@ -45,11 +40,7 @@ static void handler(struct request request, struct response _response) {
return; return;
} }
if (response.output == NULL) { response.output(out, response._userData);
fprintf(out, "Internal Server Error\n");
} else {
response.output(out, response._userData);
}
fclose(out); fclose(out);
} }

View file

@ -8,6 +8,9 @@
#include <headers.h> #include <headers.h>
#include <util.h> #include <util.h>
#include <mime.h> #include <mime.h>
#include <status.h>
#include <json.h>
#include "request.h" #include "request.h"
@ -20,11 +23,23 @@ response_t emptyResponse() {
}; };
} }
static errorformat_t errorformat = JSON;
void setDefaultErrorFormat(errorformat_t format) {
errorformat = format;
}
void _rawOutputAndFree(FILE* out, void* _userData) {
fprintf(out, "%s", (char*) _userData);
free(_userData);
}
void _rawOutput(FILE* out, void* _userData) { void _rawOutput(FILE* out, void* _userData) {
fprintf(out, "%s", (const char*) _userData); fprintf(out, "%s", (const char*) _userData);
} }
response_t rawResponse(int status, const char* txt) { response_t _rawResponse(int status, char* txt, bool free) {
response_t response = emptyResponse(); response_t response = emptyResponse();
response.status = status; response.status = status;
@ -35,10 +50,50 @@ response_t rawResponse(int status, const char* txt) {
headers_mod(&response.headers, "Content-Length", tmp); headers_mod(&response.headers, "Content-Length", tmp);
response._userData = (void*) txt; response._userData = (void*) txt;
response.output = _rawOutput;
if (free) {
response.output = _rawOutputAndFree;
} else {
response.output = _rawOutput;
}
return response; return response;
} }
response_t rawResponse(int status, const char* txt) {
return _rawResponse(status, (char*) txt, false);
}
response_t errorResponse(int status, const char* message) {
const char* statusString = getStatusStrings(status).statusString;
if (message == NULL) {
message = "";
}
char* tmp;
switch(errorformat) {
case RAW:
tmp = malloc(strlen(statusString) + 1 + strlen(message) + 1);
sprintf(tmp, "%s\n%s", statusString, message);
return _rawResponse(status, tmp, true);
case JSON:
tmp = getTimestamp();
jsonValue_t* json = json_object(true, 5,
"timestamp", json_string(tmp),
"status", json_long(status),
"error", json_string(statusString),
"message", json_string(message),
"path", json_string("not yet implemented")
);
free(tmp);
tmp = json_stringify(json);
json_free(json);
return _rawResponse(status, tmp, true);
default:
return rawResponse(500, "Internel Server Error\nunknown error format");
}
}
void _fileOutput(FILE* out, void* _userData) { void _fileOutput(FILE* out, void* _userData) {
FILE* in = (FILE*) _userData; FILE* in = (FILE*) _userData;
@ -58,16 +113,16 @@ response_t fileResponse(const char* file) {
struct stat statObj; struct stat statObj;
if (stat(file, &statObj) < 0) { if (stat(file, &statObj) < 0) {
return rawResponse(500, strerror(errno)); return errorResponse(500, strerror(errno));
} }
if (!S_ISREG(statObj.st_mode)) { if (!S_ISREG(statObj.st_mode)) {
return rawResponse(500, "not a file"); return errorResponse(500, "not a file");
} }
FILE* stream = fopen(file, "r"); FILE* stream = fopen(file, "r");
if (stream == NULL) { if (stream == NULL) {
return rawResponse(500, ""); return errorResponse(500, strerror(errno));
} }
int length = strlenOfNumber(statObj.st_size); int length = strlenOfNumber(statObj.st_size);

View file

@ -12,6 +12,8 @@ typedef struct {
method_t method; method_t method;
const char* path; const char* path;
const char* queryString; const char* queryString;
const char* peerAddr;
int peerPort;
} ctx_t; } ctx_t;
typedef struct { typedef struct {
@ -22,8 +24,17 @@ typedef struct {
void (*output) (FILE* conenction, void* _userData); void (*output) (FILE* conenction, void* _userData);
} response_t; } response_t;
typedef enum {
RAW,
JSON
} errorformat_t;
void setDefaultErrorFormat(errorformat_t format);
response_t emptyResponse(); response_t emptyResponse();
response_t errorResponse(int status, const char* message);
response_t rawResponse(int status, const char* txt); response_t rawResponse(int status, const char* txt);
response_t fileResponse(const char* file); response_t fileResponse(const char* file);

View file

@ -107,7 +107,7 @@ int registerRoute(method_t method, const char* path, handle_t* handle) {
response_t routerHandler(ctx_t ctx) { response_t routerHandler(ctx_t ctx) {
struct route* route = findRoute(ctx.method, ctx.path); struct route* route = findRoute(ctx.method, ctx.path);
if (route == NULL) { if (route == NULL) {
return rawResponse(404, "Not Found\n"); return errorResponse(404, "no route found");
} }
return route->handle(ctx); return route->handle(ctx);