1/*	$OpenBSD: http.h,v 1.12 2021/03/24 20:59:53 benno Exp $	*/
2
3/*
4 * Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#ifndef HTTP_H
20#define HTTP_H
21
22#include <sys/queue.h>
23
24#define HTTP_PORT	80
25#define HTTPS_PORT	443
26
27enum httpmethod {
28	HTTP_METHOD_NONE	= 0,
29
30	/* HTTP/1.1, RFC 7231 */
31	HTTP_METHOD_GET,
32	HTTP_METHOD_HEAD,
33	HTTP_METHOD_POST,
34	HTTP_METHOD_PUT,
35	HTTP_METHOD_DELETE,
36	HTTP_METHOD_OPTIONS,
37	HTTP_METHOD_TRACE,
38	HTTP_METHOD_CONNECT,
39
40	/* WebDAV, RFC 4918 */
41	HTTP_METHOD_PROPFIND,
42	HTTP_METHOD_PROPPATCH,
43	HTTP_METHOD_MKCOL,
44	HTTP_METHOD_COPY,
45	HTTP_METHOD_MOVE,
46	HTTP_METHOD_LOCK,
47	HTTP_METHOD_UNLOCK,
48
49	/* WebDAV Versioning Extension, RFC 3253 */
50	HTTP_METHOD_VERSION_CONTROL,
51	HTTP_METHOD_REPORT,
52	HTTP_METHOD_CHECKOUT,
53	HTTP_METHOD_CHECKIN,
54	HTTP_METHOD_UNCHECKOUT,
55	HTTP_METHOD_MKWORKSPACE,
56	HTTP_METHOD_UPDATE,
57	HTTP_METHOD_LABEL,
58	HTTP_METHOD_MERGE,
59	HTTP_METHOD_BASELINE_CONTROL,
60	HTTP_METHOD_MKACTIVITY,
61
62	/* WebDAV Ordered Collections, RFC 3648 */
63	HTTP_METHOD_ORDERPATCH,
64
65	/* WebDAV Access Control, RFC 3744 */
66	HTTP_METHOD_ACL,
67
68	/* WebDAV Redirect Reference Resources, RFC 4437 */
69	HTTP_METHOD_MKREDIRECTREF,
70	HTTP_METHOD_UPDATEREDIRECTREF,
71
72	/* WebDAV Search, RFC 5323 */
73	HTTP_METHOD_SEARCH,
74
75	/* PATCH, RFC 5789 */
76	HTTP_METHOD_PATCH,
77
78	/* Server response (internal value) */
79	HTTP_METHOD_RESPONSE
80};
81
82struct http_method {
83	enum httpmethod		 method_id;
84	const char		*method_name;
85};
86#define HTTP_METHODS		{			\
87	{ HTTP_METHOD_GET,		"GET" },	\
88	{ HTTP_METHOD_HEAD,		"HEAD" },	\
89	{ HTTP_METHOD_POST,		"POST" },	\
90	{ HTTP_METHOD_PUT,		"PUT" },	\
91	{ HTTP_METHOD_DELETE,		"DELETE" },	\
92	{ HTTP_METHOD_OPTIONS,		"OPTIONS" },	\
93	{ HTTP_METHOD_TRACE,		"TRACE" },	\
94	{ HTTP_METHOD_CONNECT,		"CONNECT" },	\
95	{ HTTP_METHOD_PROPFIND,		"PROPFIND" },	\
96	{ HTTP_METHOD_PROPPATCH,	"PROPPATCH" },	\
97	{ HTTP_METHOD_MKCOL,		"MKCOL" },	\
98	{ HTTP_METHOD_COPY,		"COPY" },	\
99	{ HTTP_METHOD_MOVE,		"MOVE" },	\
100	{ HTTP_METHOD_LOCK,		"LOCK" },	\
101	{ HTTP_METHOD_UNLOCK,		"UNLOCK" },	\
102	{ HTTP_METHOD_VERSION_CONTROL,	"VERSION-CONTROL" }, \
103	{ HTTP_METHOD_REPORT,		"REPORT" },	\
104	{ HTTP_METHOD_CHECKOUT,		"CHECKOUT" },	\
105	{ HTTP_METHOD_CHECKIN,		"CHECKIN" },	\
106	{ HTTP_METHOD_UNCHECKOUT,	"UNCHECKOUT" },	\
107	{ HTTP_METHOD_MKWORKSPACE,	"MKWORKSPACE" }, \
108	{ HTTP_METHOD_UPDATE,		"UPDATE" },	\
109	{ HTTP_METHOD_LABEL,		"LABEL" },	\
110	{ HTTP_METHOD_MERGE,		"MERGE" },	\
111	{ HTTP_METHOD_BASELINE_CONTROL,	"BASELINE-CONTROL" }, \
112	{ HTTP_METHOD_MKACTIVITY,	"MKACTIVITY" },	\
113	{ HTTP_METHOD_ORDERPATCH,	"ORDERPATCH" },	\
114	{ HTTP_METHOD_ACL,		"ACL" },	\
115	{ HTTP_METHOD_MKREDIRECTREF,	"MKREDIRECTREF" }, \
116	{ HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" }, \
117	{ HTTP_METHOD_SEARCH,		"SEARCH" },	\
118	{ HTTP_METHOD_PATCH,		"PATCH" },	\
119	{ HTTP_METHOD_NONE,		NULL }		\
120}
121
122struct http_error {
123	int			 error_code;
124	const char		*error_name;
125};
126
127/*
128 * HTTP status codes based on IANA assignments (2014-06-11 version):
129 * https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
130 * plus legacy (306) and non-standard (420).
131 */
132#define HTTP_ERRORS		{			\
133	{ 100,	"Continue" },				\
134	{ 101,	"Switching Protocols" },		\
135	{ 102,	"Processing" },				\
136	/* 103-199 unassigned */			\
137	{ 200,	"OK" },					\
138	{ 201,	"Created" },				\
139	{ 202,	"Accepted" },				\
140	{ 203,	"Non-Authoritative Information" },	\
141	{ 204,	"No Content" },				\
142	{ 205,	"Reset Content" },			\
143	{ 206,	"Partial Content" },			\
144	{ 207,	"Multi-Status" },			\
145	{ 208,	"Already Reported" },			\
146	/* 209-225 unassigned */			\
147	{ 226,	"IM Used" },				\
148	/* 227-299 unassigned */			\
149	{ 300,	"Multiple Choices" },			\
150	{ 301,	"Moved Permanently" },			\
151	{ 302,	"Found" },				\
152	{ 303,	"See Other" },				\
153	{ 304,	"Not Modified" },			\
154	{ 305,	"Use Proxy" },				\
155	{ 306,	"Switch Proxy" },			\
156	{ 307,	"Temporary Redirect" },			\
157	{ 308,	"Permanent Redirect" },			\
158	/* 309-399 unassigned */			\
159	{ 400,	"Bad Request" },			\
160	{ 401,	"Unauthorized" },			\
161	{ 402,	"Payment Required" },			\
162	{ 403,	"Forbidden" },				\
163	{ 404,	"Not Found" },				\
164	{ 405,	"Method Not Allowed" },			\
165	{ 406,	"Not Acceptable" },			\
166	{ 407,	"Proxy Authentication Required" },	\
167	{ 408,	"Request Timeout" },			\
168	{ 409,	"Conflict" },				\
169	{ 410,	"Gone" },				\
170	{ 411,	"Length Required" },			\
171	{ 412,	"Precondition Failed" },		\
172	{ 413,	"Payload Too Large" },			\
173	{ 414,	"URI Too Long" },			\
174	{ 415,	"Unsupported Media Type" },		\
175	{ 416,	"Range Not Satisfiable" },		\
176	{ 417,	"Expectation Failed" },			\
177	{ 418,	"I'm a teapot" },			\
178	/* 419-421 unassigned */			\
179	{ 420,	"Enhance Your Calm" },			\
180	{ 422,	"Unprocessable Entity" },		\
181	{ 423,	"Locked" },				\
182	{ 424,	"Failed Dependency" },			\
183	/* 425 unassigned */				\
184	{ 426,	"Upgrade Required" },			\
185	/* 427 unassigned */				\
186	{ 428,	"Precondition Required" },		\
187	{ 429,	"Too Many Requests" },			\
188	/* 430 unassigned */				\
189	{ 431,	"Request Header Fields Too Large" },	\
190	/* 432-450 unassigned */			\
191	{ 451,	"Unavailable For Legal Reasons" },	\
192	/* 452-499 unassigned */			\
193	{ 500,	"Internal Server Error" },		\
194	{ 501,	"Not Implemented" },			\
195	{ 502,	"Bad Gateway" },			\
196	{ 503,	"Service Unavailable" },		\
197	{ 504,	"Gateway Timeout" },			\
198	{ 505,	"HTTP Version Not Supported" },		\
199	{ 506,	"Variant Also Negotiates" },		\
200	{ 507,	"Insufficient Storage" },		\
201	{ 508,	"Loop Detected" },			\
202	/* 509 unassigned */				\
203	{ 510,	"Not Extended" },			\
204	{ 511,	"Network Authentication Required" },	\
205	/* 512-599 unassigned */			\
206	{ 0,	NULL }					\
207}
208
209struct http_mediatype {
210	char		*media_name;
211	char		*media_type;
212	char		*media_subtype;
213};
214/*
215 * Some default media types based on (2014-08-04 version):
216 * https://www.iana.org/assignments/media-types/media-types.xhtml
217 */
218#define MEDIA_TYPES		{			\
219	{ "css",	"text",		"css" },	\
220	{ "html",	"text",		"html" },	\
221	{ "txt",	"text",		"plain" },	\
222	{ "gif",	"image",	"gif" },	\
223	{ "jpeg",	"image",	"jpeg" },	\
224	{ "jpg",	"image",	"jpeg" },	\
225	{ "png",	"image",	"png" },	\
226	{ "svg",	"image",	"svg+xml" },	\
227	{ "js",		"application",	"javascript" },	\
228	{ NULL }					\
229}
230
231/* Used during runtime */
232struct http_descriptor {
233	struct kv		 http_pathquery;
234	struct kv		 http_matchquery;
235#define http_path		 http_pathquery.kv_key
236#define http_query		 http_pathquery.kv_value
237#define http_rescode		 http_pathquery.kv_key
238#define http_resmesg		 http_pathquery.kv_value
239#define query_key		 http_matchquery.kv_key
240#define query_val		 http_matchquery.kv_value
241
242	char			*http_host;
243	enum httpmethod		 http_method;
244	int			 http_chunked;
245	char			*http_version;
246	unsigned int		 http_status;
247
248	/* Rewritten path remains NULL if not used */
249	char			*http_path_alias;
250
251	/* A tree of headers and attached lists for repeated headers. */
252	struct kv		*http_lastheader;
253	struct kvtree		 http_headers;
254};
255
256struct http_method_node {
257	enum httpmethod			hmn_method;
258	SIMPLEQ_ENTRY(http_method_node)	hmn_entry;
259};
260
261struct http_session {
262	SIMPLEQ_HEAD(, http_method_node) hs_methods;
263};
264
265#endif /* HTTP_H */
266