blob: 9da2af85772722c4d6a5236944f96d08609ed5c7 [file] [log] [blame]
Willy Tarreau35b51c62018-09-10 15:38:55 +02001/*
2 * include/common/http.h
3 *
4 * Version-agnostic and implementation-agnostic HTTP protocol definitions.
5 *
6 * Copyright (C) 2000-2018 Willy Tarreau - w@1wt.eu
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation, version 2.1
11 * exclusively.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifndef _COMMON_HTTP_H
24#define _COMMON_HTTP_H
25
26#include <common/buf.h>
27#include <common/ist.h>
28
29/* these macros are used mainly when parsing header fields */
30#define HTTP_FLG_CTL 0x01
31#define HTTP_FLG_SEP 0x02
32#define HTTP_FLG_LWS 0x04
33#define HTTP_FLG_SPHT 0x08
34#define HTTP_FLG_CRLF 0x10
35#define HTTP_FLG_TOK 0x20
36#define HTTP_FLG_VER 0x40
37#define HTTP_FLG_DIG 0x80
38
39#define HTTP_IS_CTL(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_CTL)
40#define HTTP_IS_SEP(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_SEP)
41#define HTTP_IS_LWS(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_LWS)
42#define HTTP_IS_SPHT(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_SPHT)
43#define HTTP_IS_CRLF(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_CRLF)
44#define HTTP_IS_TOKEN(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_TOK)
45#define HTTP_IS_VER_TOKEN(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_VER)
46#define HTTP_IS_DIGIT(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_DIG)
47
48/* Known HTTP methods */
49enum http_meth_t {
50 HTTP_METH_OPTIONS,
51 HTTP_METH_GET,
52 HTTP_METH_HEAD,
53 HTTP_METH_POST,
54 HTTP_METH_PUT,
55 HTTP_METH_DELETE,
56 HTTP_METH_TRACE,
57 HTTP_METH_CONNECT,
58 HTTP_METH_OTHER, /* Must be the last entry */
59} __attribute__((packed));
60
61/* Known HTTP authentication schemes */
62enum ht_auth_m {
63 HTTP_AUTH_WRONG = -1, /* missing or unknown */
64 HTTP_AUTH_UNKNOWN = 0,
65 HTTP_AUTH_BASIC,
66 HTTP_AUTH_DIGEST,
67} __attribute__((packed));
68
69/* All implemented HTTP status codes */
70enum {
71 HTTP_ERR_200 = 0,
72 HTTP_ERR_400,
73 HTTP_ERR_403,
74 HTTP_ERR_405,
75 HTTP_ERR_408,
76 HTTP_ERR_421,
77 HTTP_ERR_425,
78 HTTP_ERR_429,
79 HTTP_ERR_500,
80 HTTP_ERR_502,
81 HTTP_ERR_503,
82 HTTP_ERR_504,
83 HTTP_ERR_SIZE
84};
85
86/* Note: the strings below make use of chunks. Chunks may carry an allocated
87 * size in addition to the length. The size counts from the beginning (str)
88 * to the end. If the size is unknown, it MUST be zero, in which case the
89 * sample will automatically be duplicated when a change larger than <len> has
90 * to be performed. Thus it is safe to always set size to zero.
91 */
92struct http_meth {
93 enum http_meth_t meth;
94 struct buffer str;
95};
96
97struct http_auth_data {
98 enum ht_auth_m method; /* one of HTTP_AUTH_* */
99 /* 7 bytes unused here */
100 struct buffer method_data; /* points to the creditial part from 'Authorization:' header */
101 char *user, *pass; /* extracted username & password */
102};
103
104struct http_method_desc {
105 enum http_meth_t meth;
106 const struct ist text;
107};
108
109extern const int http_err_codes[HTTP_ERR_SIZE];
110extern struct buffer http_err_chunks[HTTP_ERR_SIZE];
111const struct ist http_known_methods[HTTP_METH_OTHER];
112extern const uint8_t http_char_classes[256];
Willy Tarreau04f1e2d2018-09-10 18:04:24 +0200113
114const struct ist HTTP_100;
115extern const char *HTTP_301;
Willy Tarreau35b51c62018-09-10 15:38:55 +0200116extern const char *HTTP_302;
117extern const char *HTTP_303;
Willy Tarreau04f1e2d2018-09-10 18:04:24 +0200118extern const char *HTTP_307;
119extern const char *HTTP_308;
120extern const char *HTTP_401_fmt;
121extern const char *HTTP_407_fmt;
Willy Tarreau35b51c62018-09-10 15:38:55 +0200122
Willy Tarreau04f1e2d2018-09-10 18:04:24 +0200123int init_http(char **err);
Willy Tarreau35b51c62018-09-10 15:38:55 +0200124enum http_meth_t find_http_meth(const char *str, const int len);
Willy Tarreau04f1e2d2018-09-10 18:04:24 +0200125const int http_get_status_idx(unsigned int status);
126const char *http_get_reason(unsigned int status);
Willy Tarreau6b952c82018-09-10 17:45:34 +0200127struct ist http_get_path(const struct ist uri);
Willy Tarreauab813a42018-09-10 18:41:28 +0200128int http_header_match2(const char *hdr, const char *end,
129 const char *name, int len);
130char *http_find_hdr_value_end(char *s, const char *e);
131char *http_find_cookie_value_end(char *s, const char *e);
132char *http_extract_cookie_value(char *hdr, const char *hdr_end,
133 char *cookie_name, size_t cookie_name_l,
134 int list, char **value, size_t *value_l);
135int http_parse_qvalue(const char *qvalue, const char **end);
136const char *http_find_url_param_pos(const char **chunks,
137 const char* url_param_name,
138 size_t url_param_name_l, char delim);
139int http_find_next_url_param(const char **chunks,
140 const char* url_param_name, size_t url_param_name_l,
141 const char **vstart, const char **vend, char delim);
142
143/*
144 * Given a path string and its length, find the position of beginning of the
145 * query string. Returns NULL if no query string is found in the path.
146 *
147 * Example: if path = "/foo/bar/fubar?yo=mama;ye=daddy", and n = 22:
148 *
149 * find_query_string(path, n, '?') points to "yo=mama;ye=daddy" string.
150 */
151static inline char *http_find_param_list(char *path, size_t path_l, char delim)
152{
153 char *p;
154
155 p = memchr(path, delim, path_l);
156 return p ? p + 1 : NULL;
157}
158
159static inline int http_is_param_delimiter(char c, char delim)
160{
161 return c == '&' || c == ';' || c == delim;
162}
163
Willy Tarreau79e57332018-10-02 16:01:16 +0200164/* Match language range with language tag. RFC2616 14.4:
165 *
166 * A language-range matches a language-tag if it exactly equals
167 * the tag, or if it exactly equals a prefix of the tag such
168 * that the first tag character following the prefix is "-".
169 *
170 * Return 1 if the strings match, else return 0.
171 */
172static inline int http_language_range_match(const char *range, int range_len,
173 const char *tag, int tag_len)
174{
175 const char *end = range + range_len;
176 const char *tend = tag + tag_len;
177
178 while (range < end) {
179 if (*range == '-' && tag == tend)
180 return 1;
181 if (*range != *tag || tag == tend)
182 return 0;
183 range++;
184 tag++;
185 }
186 /* Return true only if the last char of the tag is matched. */
187 return tag == tend;
188}
189
Willy Tarreau35b51c62018-09-10 15:38:55 +0200190
191#endif /* _COMMON_HTTP_H */
192
193/*
194 * Local variables:
195 * c-indent-level: 8
196 * c-basic-offset: 8
197 * End:
198 */