2f5e2be18adf9c0d45dc60e7de3a444011fedf87
Christian Fraß [upd] server:lib:plankton

Christian Fraß authored 3 years ago

1) /*
2) This file is part of »bacterio-plankton:http«.
3) 
4) Copyright 2016-2021 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
5) <info@greenscale.de>
6) 
7) »bacterio-plankton:http« is free software: you can redistribute it and/or modify
8) it under the terms of the GNU Lesser General Public License as published by
9) the Free Software Foundation, either version 3 of the License, or
10) (at your option) any later version.
11) 
12) »bacterio-plankton:http« is distributed in the hope that it will be useful,
13) but WITHOUT ANY WARRANTY; without even the implied warranty of
14) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15) GNU Lesser General Public License for more details.
16) 
17) You should have received a copy of the GNU Lesser General Public License
18) along with »bacterio-plankton:http«. If not, see <http://www.gnu.org/licenses/>.
19)  */
20) var lib_http;
21) (function (lib_http) {
22)     /**
23)      * @author fenris <frass@greenscale.de>
24)      */
25)     let enum_method;
26)     (function (enum_method) {
27)         enum_method["get"] = "get";
28)         enum_method["post"] = "post";
29)         enum_method["options"] = "options";
30)         // put = "put",
31)         // delete = "delete",
32)         // head = "head",
33)     })(enum_method = lib_http.enum_method || (lib_http.enum_method = {}));
34) })(lib_http || (lib_http = {}));
35) /*
36) This file is part of »bacterio-plankton:http«.
37) 
38) Copyright 2016-2021 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
39) <info@greenscale.de>
40) 
41) »bacterio-plankton:http« is free software: you can redistribute it and/or modify
42) it under the terms of the GNU Lesser General Public License as published by
43) the Free Software Foundation, either version 3 of the License, or
44) (at your option) any later version.
45) 
46) »bacterio-plankton:http« is distributed in the hope that it will be useful,
47) but WITHOUT ANY WARRANTY; without even the implied warranty of
48) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49) GNU Lesser General Public License for more details.
50) 
51) You should have received a copy of the GNU Lesser General Public License
52) along with »bacterio-plankton:http«. If not, see <http://www.gnu.org/licenses/>.
53)  */
54) var lib_http;
55) (function (lib_http) {
56)     /**
57)      * @author fenris <frass@greenscale.de>
58)      */
59)     const linebreak = "\r\n";
60)     /**
61)      * @author fenris <frass@greenscale.de>
62)      */
63)     function encode_method(method) {
64)         switch (method) {
65)             case lib_http.enum_method.get: return "GET";
66)             case lib_http.enum_method.post: return "POST";
67)             case lib_http.enum_method.options: return "OPTIONS";
68)             default: throw (new Error("impossible"));
69)         }
70)     }
71)     /**
72)      * @author fenris <frass@greenscale.de>
73)      */
74)     function decode_method(method_raw) {
75)         switch (method_raw) {
76)             case "GET": return lib_http.enum_method.get;
77)             case "POST": return lib_http.enum_method.post;
78)             case "OPTIONS": return lib_http.enum_method.options;
79)             default: throw (new Error("unhandled method: " + method_raw));
80)         }
81)     }
82)     /**
83)      * @author fenris <frass@greenscale.de>
84)      */
85)     function get_statustext(statuscode) {
86)         switch (statuscode) {
87)             case 100: return "Continue";
88)             case 101: return "Switching Protocols";
89)             case 103: return "Early Hints";
90)             case 200: return "OK";
91)             case 201: return "Created";
92)             case 202: return "Accepted";
93)             case 203: return "Non-Authoritative Information";
94)             case 204: return "No Content";
95)             case 205: return "Reset Content";
96)             case 206: return "Partial Content";
97)             case 300: return "Multiple Choices";
98)             case 301: return "Moved Permanently";
99)             case 302: return "Found";
100)             case 303: return "See Other";
101)             case 304: return "Not Modified";
102)             case 307: return "Temporary Redirect";
103)             case 308: return "Permanent Redirect";
104)             case 400: return "Bad Request";
105)             case 401: return "Unauthorized";
106)             case 402: return "Payment Required";
107)             case 403: return "Forbidden";
108)             case 404: return "Not Found";
109)             case 405: return "Method Not Allowed";
110)             case 406: return "Not Acceptable";
111)             case 407: return "Proxy Authentication Required";
112)             case 408: return "Request Timeout";
113)             case 409: return "Conflict";
114)             case 410: return "Gone";
115)             case 411: return "Length Required";
116)             case 412: return "Precondition Failed";
117)             case 413: return "Payload Too Large";
118)             case 414: return "URI Too Long";
119)             case 415: return "Unsupported Media Type";
120)             case 416: return "Range Not Satisfiable";
121)             case 417: return "Expectation Failed";
122)             case 418: return "I'm a teapot";
123)             case 422: return "Unprocessable Entity";
124)             case 425: return "Too Early";
125)             case 426: return "Upgrade Required";
126)             case 428: return "Precondition Required";
127)             case 429: return "Too Many Requests";
128)             case 431: return "Request Header Fields Too Large";
129)             case 451: return "Unavailable For Legal Reasons";
130)             case 500: return "Internal Server Error";
131)             case 501: return "Not Implemented";
132)             case 502: return "Bad Gateway";
133)             case 503: return "Service Unavailable";
134)             case 504: return "Gateway Timeout";
135)             case 505: return "HTTP Version Not Supported";
136)             case 506: return "Variant Also Negotiates";
137)             case 507: return "Insufficient Storage";
138)             case 508: return "Loop Detected";
139)             case 510: return "Not Extended";
140)             case 511: return "Network Authentication";
141)             default: throw (new Error("unhandled statuscode: " + statuscode.toFixed(0)));
142)         }
143)     }
144)     /**
145)      * @author fenris <frass@greenscale.de>
146)      */
147)     function encode_request(request) {
148)         let request_raw = "";
149)         request_raw += (encode_method(request.method) + " " + request.query + " " + "HTTP/1.1" + linebreak);
150)         request_raw += ("Host: " + request.host + linebreak);
151)         for (const [key, value] of Object.entries(request.headers)) {
152)             request_raw += (key + ": " + value + linebreak);
153)         }
154)         request_raw += linebreak;
155)         request_raw += request.body;
156)         return request_raw;
157)     }
158)     lib_http.encode_request = encode_request;
159)     /**
160)      * @author fenris <frass@greenscale.de>
161)      */
162)     function decode_request(request_raw) {
163)         const lines = request_raw.split(linebreak);
164)         const first = lines.shift();
165)         const [method_raw, query, version] = first.split(" ");
166)         let headers = {};
167)         while (true) {
168)             const line = lines.shift();
169)             if (line === "") {
170)                 break;
171)             }
172)             else {
173)                 const [key, value] = line.split(": ", 2);
174)                 headers[key] = value;
175)             }
176)         }
177)         const body = lines.join(linebreak);
178)         const request = {
179)             "host": headers["Host"],
180)             "query": query,
181)             "method": decode_method(method_raw),
182)             "headers": headers,
183)             "body": body,
184)         };
185)         return request;
186)     }
187)     lib_http.decode_request = decode_request;
188)     /**
189)      * @author fenris <frass@greenscale.de>
190)      */
191)     function encode_response(response) {
192)         let response_raw = "";
193)         response_raw += ("HTTP/1.1" + " " + response.statuscode + " " + get_statustext(response.statuscode) + linebreak);
194)         for (const [key, value] of Object.entries(response.headers)) {
195)             response_raw += (key + ": " + value + linebreak);
196)         }
197)         response_raw += linebreak;
198)         response_raw += response.body;
199)         return response_raw;
200)     }
201)     lib_http.encode_response = encode_response;
202)     /**
203)      * @author fenris <frass@greenscale.de>
204)      */
205)     function decode_response(response_raw) {
206)         const lines = response_raw.split(linebreak);
207)         const first = lines.shift();
208)         const statuscode = parseInt(first.split(" ")[1]);
209)         let headers = {};
210)         while (true) {
211)             const line = lines.shift();
212)             if (line === "") {
213)                 break;
214)             }
215)             else {
216)                 const [key, value] = line.split(": ", 2);
217)                 headers[key] = value;
218)             }
219)         }
220)         const body = lines.join(linebreak);
221)         const response = {
222)             "statuscode": statuscode,
223)             "headers": headers,
224)             "body": body,
225)         };
226)         return response;
227)     }
228)     lib_http.decode_response = decode_response;
229) })(lib_http || (lib_http = {}));