summaryrefslogtreecommitdiff
path: root/http.c
blob: 3521e3259aef636ebe232d4cc8d2634ce4c27a44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "http.h"

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct http_request http_parse_request(const char *reqstr)
{
	char uribuf[CFWS_MAXURI];
	size_t urilen = 0, query_len = 0;
	const char *counter;

	struct http_request req;
	req.method    = HTTP_METHOD_UNKNOWN;
	req.uri       = NULL;
	req.query_str = NULL;
	req.body      = NULL;

	if (strncmp(reqstr, "GET ", 4) == 0) {
		req.method = HTTP_METHOD_GET;
		counter = reqstr + 4;
	} else if (strncmp(reqstr, "POST ", 5) == 0) {
		req.method = HTTP_METHOD_POST;
		counter = reqstr + 5;
	} else {
		fprintf(stderr, "Unhandled request type: %s\n", reqstr);
		return req;
	}

	while (*counter != ' ' && *counter != '?' && *counter != 0
			&& urilen < CFWS_MAXURI) {
		uribuf[urilen++] = *counter;
		++counter;
	}

	req.uri = malloc(urilen + 1);
	memcpy(req.uri, uribuf, urilen);
	req.uri[urilen] = '\0';

	/* Parse the query string if one exists. */
	if (*counter == '?') {
		/* Skip the question mark at the beginning. */
		counter++;

		while (*counter != ' ' && *counter != 0
				&& query_len < CFWS_MAXURI) {
			uribuf[query_len++] = *counter;
			++counter;
		}

		req.query_str = malloc(query_len + 1);
		memcpy(req.query_str, uribuf, query_len);
		req.query_str[query_len] = '\0';
	}
	
	/* TODO: Parse request headers. For now they are just ignored. */
	counter = strstr(reqstr, "\r\n\r\n");
	if (req.method == HTTP_METHOD_POST) {
		size_t body_len;
		counter += 4;

		body_len = strlen(counter);
		req.body = malloc(body_len + 1);
		memcpy(req.body, counter, body_len);
		req.body[body_len] = '\0';
	}

	return req;
}

void http_free_request(struct http_request *req)
{
	free(req->uri);
	if (req->query_str)
		free(req->query_str);
	if (req->body)
		free(req->body);
}

static const char *response_msg[] = {
	"200 OK",
	"400 Bad Request",
	"404 Not Found",
	"501 Not Implemented"
};

void http_response_statusline(enum http_res_code status_code, int sockfd)
{
	char statusline[64];
	int len;
	len = snprintf(statusline, 64, "HTTP/1.1 %s\r\n", response_msg[status_code]);
	write(sockfd, statusline, len);
}