-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp.cpp
110 lines (79 loc) · 3.37 KB
/
http.cpp
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <string>
#include <vector>
#include <unordered_map>
#include <stdbool.h>
#include <stdint.h>
#include "split_string.hpp"
#include "string_startswith.hpp"
#include "http.hpp"
std::unordered_map<std::string, std::string> LHTTP::mimeTable = {
{"html", "text/html"},
{"txt", "text/plain"},
{"css", "text/css"},
{"js", "text/javascript"},
{"png", "image/png"},
{"webp", "image/webp"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"ico", "image/x-icon"}
};
std::vector<std::string> LHTTP::requestTypes = {"GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE", "POST", "PATCH", "CONNECT"};
// takes a file like "/images/screenshot.png" and gets
// a mime type out of it like "image/png"
// note this will break if i add support for more data in the url than just a path
std::string LHTTP::get_MIME_from_filename(std::string filename) {
std::vector filepathVect = split_string(filename, "/");
// if there is no file extension, return plaintext
if (filepathVect[filepathVect.size()-1].find('.') == std::string::npos)
return "text/plain";
std::vector<std::string> filenameVect = split_string(
filepathVect[filepathVect.size()-1], "."
);
std::string fileExt = filenameVect[filenameVect.size()-1];
auto element = mimeTable.find(fileExt);
// if mime type not found in map, return plaintext
if (element == mimeTable.end())
return "text/plain";
return mimeTable[fileExt];
}
// turns an http request into key-value pairs for each "variable"
// example
// GET /example/path HTTP/1.1
// User-Agent: MyUseragent
// Connection: keep-alive
// into
// {{"ReqMethod", "GET"},
// {"ReqPath", "/example/path"},
// {"ReqVersion", "HTTP/1.1"}
// {"User-Agent", "MyUseragent"},
// {"Connection", "keep-alive"}}
// if the request has an error, return empty map
std::unordered_map<std::string, std::string> LHTTP::get_HTTP_req_params(std::string httpReq) {
std::unordered_map<std::string, std::string> resMap;
// http requests using \r\n instead of just \n is so dumb...
std::vector<std::string> reqLines = split_string(httpReq, "\r\n");
// check that a valid request method is present at the beginning of the request and store method
bool foundRequestType = false;
for (uint8_t i = 0; i < requestTypes.size(); i++) {
if (startsWith(reqLines[0].c_str(), requestTypes[i].c_str())) {
foundRequestType = true;
resMap["ReqMethod"] = requestTypes[i];
break;
}
}
// return empty map if no request type was found
if (!foundRequestType) return resMap;
// split http version from filepath
// (why did they have to make space a delimiter between the 3 parts of the first line when it can be incldued in the filepath....)
// this protocol is more fit for human reading than computer reading....
resMap["ReqVersion"] = split_string(reqLines[0], " ")[split_string(reqLines[0], " ").size()-1];
// remove the method and http version from the start and end of string to get filepath like this
// GET /hi.txt HTTP/1.1
// XXXX XXXXXXXXX
reqLines[0].erase(0,resMap["ReqMethod"].length()+1);
// i hate this line
reqLines[0].erase(reqLines[0].size()-(resMap["ReqVersion"].size()+1), resMap["ReqVersion"].size()+1);
resMap["ReqPath"] = reqLines[0];
// todo parse rest of the lines
return resMap;
}