xref: /openbsd-src/usr.sbin/httpd/http.h (revision f4ea8fe21082944c520411eb56322b4eeb490342)
1*f4ea8fe2Sjob /*	$OpenBSD: http.h,v 1.17 2024/03/24 10:53:27 job Exp $	*/
2b7b6a941Sreyk 
3b7b6a941Sreyk /*
405c2c945Sreyk  * Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org>
5b7b6a941Sreyk  *
6b7b6a941Sreyk  * Permission to use, copy, modify, and distribute this software for any
7b7b6a941Sreyk  * purpose with or without fee is hereby granted, provided that the above
8b7b6a941Sreyk  * copyright notice and this permission notice appear in all copies.
9b7b6a941Sreyk  *
10b7b6a941Sreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b7b6a941Sreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b7b6a941Sreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b7b6a941Sreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b7b6a941Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b7b6a941Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b7b6a941Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b7b6a941Sreyk  */
18b7b6a941Sreyk 
19a3e464c5Sreyk #ifndef HTTP_H
20a3e464c5Sreyk #define HTTP_H
21b7b6a941Sreyk 
226af43371Sreyk #define HTTP_PORT	80
236af43371Sreyk #define HTTPS_PORT	443
246af43371Sreyk 
25b7b6a941Sreyk enum httpmethod {
26b7b6a941Sreyk 	HTTP_METHOD_NONE	= 0,
27b7b6a941Sreyk 
2806ea06a1Sdoug 	/* HTTP/1.1, RFC 7231 */
29b7b6a941Sreyk 	HTTP_METHOD_GET,
30b7b6a941Sreyk 	HTTP_METHOD_HEAD,
31b7b6a941Sreyk 	HTTP_METHOD_POST,
32b7b6a941Sreyk 	HTTP_METHOD_PUT,
33b7b6a941Sreyk 	HTTP_METHOD_DELETE,
34b7b6a941Sreyk 	HTTP_METHOD_OPTIONS,
35b7b6a941Sreyk 	HTTP_METHOD_TRACE,
36b7b6a941Sreyk 	HTTP_METHOD_CONNECT,
37b7b6a941Sreyk 
38b7b6a941Sreyk 	/* WebDAV, RFC 4918 */
39b7b6a941Sreyk 	HTTP_METHOD_PROPFIND,
40b7b6a941Sreyk 	HTTP_METHOD_PROPPATCH,
41b7b6a941Sreyk 	HTTP_METHOD_MKCOL,
42b7b6a941Sreyk 	HTTP_METHOD_COPY,
43b7b6a941Sreyk 	HTTP_METHOD_MOVE,
44b7b6a941Sreyk 	HTTP_METHOD_LOCK,
45b7b6a941Sreyk 	HTTP_METHOD_UNLOCK,
46b7b6a941Sreyk 
47f0c872b4Sreyk 	/* WebDAV Versioning Extension, RFC 3253 */
48f0c872b4Sreyk 	HTTP_METHOD_VERSION_CONTROL,
49f0c872b4Sreyk 	HTTP_METHOD_REPORT,
50f0c872b4Sreyk 	HTTP_METHOD_CHECKOUT,
51f0c872b4Sreyk 	HTTP_METHOD_CHECKIN,
52f0c872b4Sreyk 	HTTP_METHOD_UNCHECKOUT,
53f0c872b4Sreyk 	HTTP_METHOD_MKWORKSPACE,
54f0c872b4Sreyk 	HTTP_METHOD_UPDATE,
55f0c872b4Sreyk 	HTTP_METHOD_LABEL,
56f0c872b4Sreyk 	HTTP_METHOD_MERGE,
57f0c872b4Sreyk 	HTTP_METHOD_BASELINE_CONTROL,
58f0c872b4Sreyk 	HTTP_METHOD_MKACTIVITY,
59f0c872b4Sreyk 
60f0c872b4Sreyk 	/* WebDAV Ordered Collections, RFC 3648 */
61f0c872b4Sreyk 	HTTP_METHOD_ORDERPATCH,
62f0c872b4Sreyk 
63f0c872b4Sreyk 	/* WebDAV Access Control, RFC 3744 */
64f0c872b4Sreyk 	HTTP_METHOD_ACL,
65f0c872b4Sreyk 
66f0c872b4Sreyk 	/* WebDAV Redirect Reference Resources, RFC 4437 */
67f0c872b4Sreyk 	HTTP_METHOD_MKREDIRECTREF,
68f0c872b4Sreyk 	HTTP_METHOD_UPDATEREDIRECTREF,
69f0c872b4Sreyk 
70f0c872b4Sreyk 	/* WebDAV Search, RFC 5323 */
71f0c872b4Sreyk 	HTTP_METHOD_SEARCH,
72f0c872b4Sreyk 
73b7b6a941Sreyk 	/* PATCH, RFC 5789 */
74b7b6a941Sreyk 	HTTP_METHOD_PATCH,
75b7b6a941Sreyk 
76b7b6a941Sreyk 	/* Server response (internal value) */
77b7b6a941Sreyk 	HTTP_METHOD_RESPONSE
78b7b6a941Sreyk };
79b7b6a941Sreyk 
80b7b6a941Sreyk struct http_method {
81b7b6a941Sreyk 	enum httpmethod		 method_id;
82b7b6a941Sreyk 	const char		*method_name;
83b7b6a941Sreyk };
84b7b6a941Sreyk #define HTTP_METHODS		{			\
85b7b6a941Sreyk 	{ HTTP_METHOD_GET,		"GET" },	\
86b7b6a941Sreyk 	{ HTTP_METHOD_HEAD,		"HEAD" },	\
87b7b6a941Sreyk 	{ HTTP_METHOD_POST,		"POST" },	\
88b7b6a941Sreyk 	{ HTTP_METHOD_PUT,		"PUT" },	\
89b7b6a941Sreyk 	{ HTTP_METHOD_DELETE,		"DELETE" },	\
90b7b6a941Sreyk 	{ HTTP_METHOD_OPTIONS,		"OPTIONS" },	\
91b7b6a941Sreyk 	{ HTTP_METHOD_TRACE,		"TRACE" },	\
92b7b6a941Sreyk 	{ HTTP_METHOD_CONNECT,		"CONNECT" },	\
93b7b6a941Sreyk 	{ HTTP_METHOD_PROPFIND,		"PROPFIND" },	\
94b7b6a941Sreyk 	{ HTTP_METHOD_PROPPATCH,	"PROPPATCH" },	\
95b7b6a941Sreyk 	{ HTTP_METHOD_MKCOL,		"MKCOL" },	\
96b7b6a941Sreyk 	{ HTTP_METHOD_COPY,		"COPY" },	\
97b7b6a941Sreyk 	{ HTTP_METHOD_MOVE,		"MOVE" },	\
98b7b6a941Sreyk 	{ HTTP_METHOD_LOCK,		"LOCK" },	\
99b7b6a941Sreyk 	{ HTTP_METHOD_UNLOCK,		"UNLOCK" },	\
100f0c872b4Sreyk 	{ HTTP_METHOD_VERSION_CONTROL,	"VERSION-CONTROL" }, \
101f0c872b4Sreyk 	{ HTTP_METHOD_REPORT,		"REPORT" },	\
102f0c872b4Sreyk 	{ HTTP_METHOD_CHECKOUT,		"CHECKOUT" },	\
103f0c872b4Sreyk 	{ HTTP_METHOD_CHECKIN,		"CHECKIN" },	\
104f0c872b4Sreyk 	{ HTTP_METHOD_UNCHECKOUT,	"UNCHECKOUT" },	\
105f0c872b4Sreyk 	{ HTTP_METHOD_MKWORKSPACE,	"MKWORKSPACE" }, \
106f0c872b4Sreyk 	{ HTTP_METHOD_UPDATE,		"UPDATE" },	\
107f0c872b4Sreyk 	{ HTTP_METHOD_LABEL,		"LABEL" },	\
108f0c872b4Sreyk 	{ HTTP_METHOD_MERGE,		"MERGE" },	\
109f0c872b4Sreyk 	{ HTTP_METHOD_BASELINE_CONTROL,	"BASELINE-CONTROL" }, \
110f0c872b4Sreyk 	{ HTTP_METHOD_MKACTIVITY,	"MKACTIVITY" },	\
111f0c872b4Sreyk 	{ HTTP_METHOD_ORDERPATCH,	"ORDERPATCH" },	\
112f0c872b4Sreyk 	{ HTTP_METHOD_ACL,		"ACL" },	\
113f0c872b4Sreyk 	{ HTTP_METHOD_MKREDIRECTREF,	"MKREDIRECTREF" }, \
114f0c872b4Sreyk 	{ HTTP_METHOD_UPDATEREDIRECTREF, "UPDATEREDIRECTREF" }, \
115f0c872b4Sreyk 	{ HTTP_METHOD_SEARCH,		"SEARCH" },	\
116b7b6a941Sreyk 	{ HTTP_METHOD_PATCH,		"PATCH" },	\
117b7b6a941Sreyk 	{ HTTP_METHOD_NONE,		NULL }		\
118b7b6a941Sreyk }
119b7b6a941Sreyk 
120b7b6a941Sreyk struct http_error {
121b7b6a941Sreyk 	int			 error_code;
122b7b6a941Sreyk 	const char		*error_name;
123b7b6a941Sreyk };
12406ea06a1Sdoug 
12506ea06a1Sdoug /*
12606ea06a1Sdoug  * HTTP status codes based on IANA assignments (2014-06-11 version):
12706ea06a1Sdoug  * https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
12806ea06a1Sdoug  * plus legacy (306) and non-standard (420).
12906ea06a1Sdoug  */
130b7b6a941Sreyk #define HTTP_ERRORS		{			\
131b7b6a941Sreyk 	{ 100,	"Continue" },				\
132b7b6a941Sreyk 	{ 101,	"Switching Protocols" },		\
13306ea06a1Sdoug 	{ 102,	"Processing" },				\
134*f4ea8fe2Sjob 	{ 103,	"Early Hints" },			\
135*f4ea8fe2Sjob 	/* 104-199 unassigned */			\
136b7b6a941Sreyk 	{ 200,	"OK" },					\
137b7b6a941Sreyk 	{ 201,	"Created" },				\
138b7b6a941Sreyk 	{ 202,	"Accepted" },				\
13906ea06a1Sdoug 	{ 203,	"Non-Authoritative Information" },	\
140b7b6a941Sreyk 	{ 204,	"No Content" },				\
141b7b6a941Sreyk 	{ 205,	"Reset Content" },			\
142b7b6a941Sreyk 	{ 206,	"Partial Content" },			\
14306ea06a1Sdoug 	{ 207,	"Multi-Status" },			\
14406ea06a1Sdoug 	{ 208,	"Already Reported" },			\
14506ea06a1Sdoug 	/* 209-225 unassigned */			\
14606ea06a1Sdoug 	{ 226,	"IM Used" },				\
14706ea06a1Sdoug 	/* 227-299 unassigned */			\
148b7b6a941Sreyk 	{ 300,	"Multiple Choices" },			\
149b7b6a941Sreyk 	{ 301,	"Moved Permanently" },			\
15006ea06a1Sdoug 	{ 302,	"Found" },				\
151b7b6a941Sreyk 	{ 303,	"See Other" },				\
152b7b6a941Sreyk 	{ 304,	"Not Modified" },			\
15306ea06a1Sdoug 	{ 305,	"Use Proxy" },				\
15406ea06a1Sdoug 	{ 306,	"Switch Proxy" },			\
155b7b6a941Sreyk 	{ 307,	"Temporary Redirect" },			\
15606ea06a1Sdoug 	{ 308,	"Permanent Redirect" },			\
15706ea06a1Sdoug 	/* 309-399 unassigned */			\
158b7b6a941Sreyk 	{ 400,	"Bad Request" },			\
159b7b6a941Sreyk 	{ 401,	"Unauthorized" },			\
160b7b6a941Sreyk 	{ 402,	"Payment Required" },			\
161b7b6a941Sreyk 	{ 403,	"Forbidden" },				\
162b7b6a941Sreyk 	{ 404,	"Not Found" },				\
163b7b6a941Sreyk 	{ 405,	"Method Not Allowed" },			\
164b7b6a941Sreyk 	{ 406,	"Not Acceptable" },			\
165b7b6a941Sreyk 	{ 407,	"Proxy Authentication Required" },	\
166b7b6a941Sreyk 	{ 408,	"Request Timeout" },			\
167b7b6a941Sreyk 	{ 409,	"Conflict" },				\
168b7b6a941Sreyk 	{ 410,	"Gone" },				\
169b7b6a941Sreyk 	{ 411,	"Length Required" },			\
170b7b6a941Sreyk 	{ 412,	"Precondition Failed" },		\
17106ea06a1Sdoug 	{ 413,	"Payload Too Large" },			\
17206ea06a1Sdoug 	{ 414,	"URI Too Long" },			\
173b7b6a941Sreyk 	{ 415,	"Unsupported Media Type" },		\
17406ea06a1Sdoug 	{ 416,	"Range Not Satisfiable" },		\
175b7b6a941Sreyk 	{ 417,	"Expectation Failed" },			\
176c05a8c45Sflorian 	{ 418,	"I'm a teapot" },			\
177c05a8c45Sflorian 	/* 419-421 unassigned */			\
17806ea06a1Sdoug 	{ 420,	"Enhance Your Calm" },			\
179*f4ea8fe2Sjob 	{ 422,	"Unprocessable Content" },		\
18006ea06a1Sdoug 	{ 423,	"Locked" },				\
18106ea06a1Sdoug 	{ 424,	"Failed Dependency" },			\
182*f4ea8fe2Sjob 	{ 425,	"Too Early" },			\
18306ea06a1Sdoug 	{ 426,	"Upgrade Required" },			\
18406ea06a1Sdoug 	/* 427 unassigned */				\
18506ea06a1Sdoug 	{ 428,	"Precondition Required" },		\
18606ea06a1Sdoug 	{ 429,	"Too Many Requests" },			\
18706ea06a1Sdoug 	/* 430 unassigned */				\
18806ea06a1Sdoug 	{ 431,	"Request Header Fields Too Large" },	\
189c05a8c45Sflorian 	/* 432-450 unassigned */			\
190c05a8c45Sflorian 	{ 451,	"Unavailable For Legal Reasons" },	\
191c05a8c45Sflorian 	/* 452-499 unassigned */			\
192b7b6a941Sreyk 	{ 500,	"Internal Server Error" },		\
193b7b6a941Sreyk 	{ 501,	"Not Implemented" },			\
194b7b6a941Sreyk 	{ 502,	"Bad Gateway" },			\
195b7b6a941Sreyk 	{ 503,	"Service Unavailable" },		\
196b7b6a941Sreyk 	{ 504,	"Gateway Timeout" },			\
197b7b6a941Sreyk 	{ 505,	"HTTP Version Not Supported" },		\
19806ea06a1Sdoug 	{ 506,	"Variant Also Negotiates" },		\
19906ea06a1Sdoug 	{ 507,	"Insufficient Storage" },		\
20006ea06a1Sdoug 	{ 508,	"Loop Detected" },			\
20106ea06a1Sdoug 	/* 509 unassigned */				\
20206ea06a1Sdoug 	{ 510,	"Not Extended" },			\
20306ea06a1Sdoug 	{ 511,	"Network Authentication Required" },	\
20406ea06a1Sdoug 	/* 512-599 unassigned */			\
205b7b6a941Sreyk 	{ 0,	NULL }					\
206b7b6a941Sreyk }
207b7b6a941Sreyk 
2089b9ff8ecSreyk struct http_mediatype {
2099b9ff8ecSreyk 	char		*media_name;
2109b9ff8ecSreyk 	char		*media_type;
2119b9ff8ecSreyk 	char		*media_subtype;
2129b9ff8ecSreyk };
21306ea06a1Sdoug /*
21406ea06a1Sdoug  * Some default media types based on (2014-08-04 version):
21506ea06a1Sdoug  * https://www.iana.org/assignments/media-types/media-types.xhtml
21606ea06a1Sdoug  */
2179b9ff8ecSreyk #define MEDIA_TYPES		{			\
2189b9ff8ecSreyk 	{ "css",	"text",		"css" },	\
2199b9ff8ecSreyk 	{ "html",	"text",		"html" },	\
2209b9ff8ecSreyk 	{ "txt",	"text",		"plain" },	\
2219b9ff8ecSreyk 	{ "gif",	"image",	"gif" },	\
2229b9ff8ecSreyk 	{ "jpeg",	"image",	"jpeg" },	\
2239b9ff8ecSreyk 	{ "jpg",	"image",	"jpeg" },	\
2249b9ff8ecSreyk 	{ "png",	"image",	"png" },	\
225d8578b6bSreyk 	{ "svg",	"image",	"svg+xml" },	\
2269b9ff8ecSreyk 	{ "js",		"application",	"javascript" },	\
2279b9ff8ecSreyk 	{ NULL }					\
2289b9ff8ecSreyk }
2299b9ff8ecSreyk 
230b7b6a941Sreyk /* Used during runtime */
231b7b6a941Sreyk struct http_descriptor {
232b7b6a941Sreyk 	struct kv		 http_pathquery;
233fb419eefSreyk 	struct kv		 http_matchquery;
234b7b6a941Sreyk #define http_path		 http_pathquery.kv_key
235b7b6a941Sreyk #define http_query		 http_pathquery.kv_value
236b7b6a941Sreyk #define http_rescode		 http_pathquery.kv_key
237b7b6a941Sreyk #define http_resmesg		 http_pathquery.kv_value
238fb419eefSreyk #define query_key		 http_matchquery.kv_key
239fb419eefSreyk #define query_val		 http_matchquery.kv_value
240b7b6a941Sreyk 
24147dc2a9dSreyk 	char			*http_host;
242b7b6a941Sreyk 	enum httpmethod		 http_method;
243b7b6a941Sreyk 	int			 http_chunked;
2446af43371Sreyk 	char			*http_version;
245a9aa5d33Sbenno 	unsigned int		 http_status;
246b7b6a941Sreyk 
247a23b6848Stb 	/* Rewritten path and query remain NULL if not used */
248de6550b1Sreyk 	char			*http_path_alias;
249a23b6848Stb 	char			*http_query_alias;
25016a88448Syasuoka 	char			*http_path_orig;
251de6550b1Sreyk 
252b7b6a941Sreyk 	/* A tree of headers and attached lists for repeated headers. */
253b7b6a941Sreyk 	struct kv		*http_lastheader;
2546af43371Sreyk 	struct kvtree		 http_headers;
255b7b6a941Sreyk };
256b7b6a941Sreyk 
257a3e464c5Sreyk #endif /* HTTP_H */
258