REORG: http: move the HTTP semantics definitions to http.h/http.c
It's a bit painful to have to deal with HTTP semantics for each protocol
version (H1 and H2), and working on the version-agnostic code further
emphasizes the problem.
This patch creates http.h and http.c which are agnostic to the version
in use, and which borrow a few parts from proto_http and from h1. For
example the once thought h1-specific h1_char_classes array is in fact
dictated by RFC7231 and is used to parse HTTP headers. A few changes
were made to a few files which were including proto_http.h while they
only needed http.h.
Certain string definitions pre-dated the introduction of indirect
strings (ist) so some were used to simplify the definition of the known
HTTP methods. The current lookup code saves 2 kB of a heavily used table
and is faster than the previous table based lookup (typ. 14 ns vs 16
before).
diff --git a/include/common/buf.h b/include/common/buf.h
index a1355e6..4208820 100644
--- a/include/common/buf.h
+++ b/include/common/buf.h
@@ -29,6 +29,7 @@
#define _COMMON_BUF_H
#include <stdint.h>
+#include <string.h>
/* Structure defining a buffer's head */
struct buffer {
diff --git a/include/common/http.h b/include/common/http.h
new file mode 100644
index 0000000..d283e29
--- /dev/null
+++ b/include/common/http.h
@@ -0,0 +1,125 @@
+/*
+ * include/common/http.h
+ *
+ * Version-agnostic and implementation-agnostic HTTP protocol definitions.
+ *
+ * Copyright (C) 2000-2018 Willy Tarreau - w@1wt.eu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, version 2.1
+ * exclusively.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _COMMON_HTTP_H
+#define _COMMON_HTTP_H
+
+#include <common/buf.h>
+#include <common/ist.h>
+
+/* these macros are used mainly when parsing header fields */
+#define HTTP_FLG_CTL 0x01
+#define HTTP_FLG_SEP 0x02
+#define HTTP_FLG_LWS 0x04
+#define HTTP_FLG_SPHT 0x08
+#define HTTP_FLG_CRLF 0x10
+#define HTTP_FLG_TOK 0x20
+#define HTTP_FLG_VER 0x40
+#define HTTP_FLG_DIG 0x80
+
+#define HTTP_IS_CTL(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_CTL)
+#define HTTP_IS_SEP(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_SEP)
+#define HTTP_IS_LWS(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_LWS)
+#define HTTP_IS_SPHT(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_SPHT)
+#define HTTP_IS_CRLF(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_CRLF)
+#define HTTP_IS_TOKEN(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_TOK)
+#define HTTP_IS_VER_TOKEN(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_VER)
+#define HTTP_IS_DIGIT(x) (http_char_classes[(uint8_t)(x)] & HTTP_FLG_DIG)
+
+/* Known HTTP methods */
+enum http_meth_t {
+ HTTP_METH_OPTIONS,
+ HTTP_METH_GET,
+ HTTP_METH_HEAD,
+ HTTP_METH_POST,
+ HTTP_METH_PUT,
+ HTTP_METH_DELETE,
+ HTTP_METH_TRACE,
+ HTTP_METH_CONNECT,
+ HTTP_METH_OTHER, /* Must be the last entry */
+} __attribute__((packed));
+
+/* Known HTTP authentication schemes */
+enum ht_auth_m {
+ HTTP_AUTH_WRONG = -1, /* missing or unknown */
+ HTTP_AUTH_UNKNOWN = 0,
+ HTTP_AUTH_BASIC,
+ HTTP_AUTH_DIGEST,
+} __attribute__((packed));
+
+/* All implemented HTTP status codes */
+enum {
+ HTTP_ERR_200 = 0,
+ HTTP_ERR_400,
+ HTTP_ERR_403,
+ HTTP_ERR_405,
+ HTTP_ERR_408,
+ HTTP_ERR_421,
+ HTTP_ERR_425,
+ HTTP_ERR_429,
+ HTTP_ERR_500,
+ HTTP_ERR_502,
+ HTTP_ERR_503,
+ HTTP_ERR_504,
+ HTTP_ERR_SIZE
+};
+
+/* Note: the strings below make use of chunks. Chunks may carry an allocated
+ * size in addition to the length. The size counts from the beginning (str)
+ * to the end. If the size is unknown, it MUST be zero, in which case the
+ * sample will automatically be duplicated when a change larger than <len> has
+ * to be performed. Thus it is safe to always set size to zero.
+ */
+struct http_meth {
+ enum http_meth_t meth;
+ struct buffer str;
+};
+
+struct http_auth_data {
+ enum ht_auth_m method; /* one of HTTP_AUTH_* */
+ /* 7 bytes unused here */
+ struct buffer method_data; /* points to the creditial part from 'Authorization:' header */
+ char *user, *pass; /* extracted username & password */
+};
+
+struct http_method_desc {
+ enum http_meth_t meth;
+ const struct ist text;
+};
+
+extern const int http_err_codes[HTTP_ERR_SIZE];
+extern struct buffer http_err_chunks[HTTP_ERR_SIZE];
+const struct ist http_known_methods[HTTP_METH_OTHER];
+extern const uint8_t http_char_classes[256];
+extern const char *HTTP_302;
+extern const char *HTTP_303;
+
+enum http_meth_t find_http_meth(const char *str, const int len);
+
+#endif /* _COMMON_HTTP_H */
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/include/proto/h1.h b/include/proto/h1.h
index eef310f..2997383 100644
--- a/include/proto/h1.h
+++ b/include/proto/h1.h
@@ -25,13 +25,12 @@
#include <common/buffer.h>
#include <common/compiler.h>
#include <common/config.h>
+#include <common/http.h>
#include <common/http-hdr.h>
#include <common/standard.h>
#include <types/h1.h>
-#include <types/proto_http.h>
#include <proto/hdr_idx.h>
-extern const uint8_t h1_char_classes[256];
const char *http_parse_reqline(struct http_msg *msg,
enum h1_state state, const char *ptr, const char *end,
unsigned int *ret_ptr, enum h1_state *ret_state);
@@ -45,25 +44,6 @@
struct h1m *h1m);
int h1_measure_trailers(const struct buffer *buf, unsigned int ofs, unsigned int max);
-#define H1_FLG_CTL 0x01
-#define H1_FLG_SEP 0x02
-#define H1_FLG_LWS 0x04
-#define H1_FLG_SPHT 0x08
-#define H1_FLG_CRLF 0x10
-#define H1_FLG_TOK 0x20
-#define H1_FLG_VER 0x40
-#define H1_FLG_DIG 0x80
-
-#define HTTP_IS_CTL(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_CTL)
-#define HTTP_IS_SEP(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_SEP)
-#define HTTP_IS_LWS(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_LWS)
-#define HTTP_IS_SPHT(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_SPHT)
-#define HTTP_IS_CRLF(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_CRLF)
-#define HTTP_IS_TOKEN(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_TOK)
-#define HTTP_IS_VER_TOKEN(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_VER)
-#define HTTP_IS_DIGIT(x) (h1_char_classes[(uint8_t)(x)] & H1_FLG_DIG)
-
-
/* Macros used in the HTTP/1 parser, to check for the expected presence of
* certain bytes (ef: LF) or to skip to next byte and yield in case of failure.
*/
diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
index 7849e15..b537d45 100644
--- a/include/proto/proto_http.h
+++ b/include/proto/proto_http.h
@@ -44,11 +44,6 @@
* ver_token = 'H', 'P', 'T', '/', '.', and digits.
*/
-extern const int http_err_codes[HTTP_ERR_SIZE];
-extern struct buffer http_err_chunks[HTTP_ERR_SIZE];
-extern const char *HTTP_302;
-extern const char *HTTP_303;
-
int process_cli(struct stream *s);
int process_srv_data(struct stream *s);
int process_srv_conn(struct stream *s);
@@ -126,8 +121,6 @@
int smp_fetch_cookie(const struct arg *args, struct sample *smp, const char *kw, void *private);
int smp_fetch_base32(const struct arg *args, struct sample *smp, const char *kw, void *private);
-enum http_meth_t find_http_meth(const char *str, const int len);
-
struct action_kw *action_http_req_custom(const char *kw);
struct action_kw *action_http_res_custom(const char *kw);
int val_hdr(struct arg *arg, char **err_msg);
diff --git a/include/types/hlua.h b/include/types/hlua.h
index 5a8173f..4fb6309 100644
--- a/include/types/hlua.h
+++ b/include/types/hlua.h
@@ -8,6 +8,7 @@
#include <common/xref.h>
+#include <types/h1.h>
#include <types/proxy.h>
#include <types/server.h>
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index 9c39056..5cb0589 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -22,8 +22,9 @@
#ifndef _TYPES_PROTO_HTTP_H
#define _TYPES_PROTO_HTTP_H
-#include <common/chunk.h>
+#include <common/buf.h>
#include <common/config.h>
+#include <common/http.h>
#include <common/mini-clist.h>
#include <common/regex.h>
@@ -31,7 +32,7 @@
#include <types/h1.h>
#include <types/hdr_idx.h>
#include <types/filters.h>
-#include <types/sample.h>
+//#include <types/sample.h>
/* These are the flags that are found in txn->flags */
@@ -170,13 +171,6 @@
PERSIST_TYPE_IGNORE, /* ignore-persist */
};
-enum ht_auth_m {
- HTTP_AUTH_WRONG = -1, /* missing or unknown */
- HTTP_AUTH_UNKNOWN = 0,
- HTTP_AUTH_BASIC,
- HTTP_AUTH_DIGEST,
-} __attribute__((packed));
-
/* final results for http-request rules */
enum rule_result {
HTTP_RULE_RES_CONT = 0, /* nothing special, continue rules evaluation */
@@ -188,25 +182,6 @@
HTTP_RULE_RES_BADREQ, /* bad request */
};
-/*
- * All implemented return codes
- */
-enum {
- HTTP_ERR_200 = 0,
- HTTP_ERR_400,
- HTTP_ERR_403,
- HTTP_ERR_405,
- HTTP_ERR_408,
- HTTP_ERR_421,
- HTTP_ERR_425,
- HTTP_ERR_429,
- HTTP_ERR_500,
- HTTP_ERR_502,
- HTTP_ERR_503,
- HTTP_ERR_504,
- HTTP_ERR_SIZE
-};
-
/* status codes available for the stats admin page */
enum {
STAT_STATUS_INIT = 0,
@@ -298,13 +273,6 @@
unsigned long long body_len; /* total known length of the body, excluding encoding */
};
-struct http_auth_data {
- enum ht_auth_m method; /* one of HTTP_AUTH_* */
- /* 7 bytes unused here */
- struct buffer method_data; /* points to the creditial part from 'Authorization:' header */
- char *user, *pass; /* extracted username & password */
-};
-
struct proxy;
struct http_txn;
struct stream;
@@ -349,16 +317,9 @@
int prev; /* index of previous header */
};
-struct http_method_name {
- char *name;
- int len;
-};
-
extern struct action_kw_list http_req_keywords;
extern struct action_kw_list http_res_keywords;
-extern const struct http_method_name http_known_methods[HTTP_METH_OTHER];
-
extern struct pool_head *pool_head_http_txn;
#endif /* _TYPES_PROTO_HTTP_H */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 2d1b881..70bfeee 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -29,6 +29,7 @@
#include <common/chunk.h>
#include <common/config.h>
+#include <common/http.h>
#include <common/mini-clist.h>
#include <common/regex.h>
#include <common/tools.h>
@@ -45,7 +46,6 @@
#include <types/listener.h>
#include <types/log.h>
#include <types/obj_type.h>
-#include <types/proto_http.h>
#include <types/sample.h>
#include <types/server.h>
#include <types/stick_table.h>
diff --git a/include/types/sample.h b/include/types/sample.h
index 987a099..015c5ae 100644
--- a/include/types/sample.h
+++ b/include/types/sample.h
@@ -26,7 +26,8 @@
#include <sys/socket.h>
#include <netinet/in.h>
-#include <common/chunk.h>
+#include <common/buf.h>
+#include <common/http.h>
#include <common/mini-clist.h>
struct arg;
@@ -210,19 +211,6 @@
struct session;
struct stream;
-/* Known HTTP methods */
-enum http_meth_t {
- HTTP_METH_OPTIONS,
- HTTP_METH_GET,
- HTTP_METH_HEAD,
- HTTP_METH_POST,
- HTTP_METH_PUT,
- HTTP_METH_DELETE,
- HTTP_METH_TRACE,
- HTTP_METH_CONNECT,
- HTTP_METH_OTHER, /* Must be the last entry */
-} __attribute__((packed));
-
/* a sample context might be used by any sample fetch function in order to
* store information needed across multiple calls (eg: restart point for a
* next occurrence). By definition it may store up to 8 pointers, or any
@@ -242,17 +230,12 @@
* sample will automatically be duplicated when a change larger than <len> has
* to be performed. Thus it is safe to always set size to zero.
*/
-struct meth {
- enum http_meth_t meth;
- struct buffer str;
-};
-
union sample_value {
long long int sint; /* used for signed 64bits integers */
struct in_addr ipv4; /* used for ipv4 addresses */
struct in6_addr ipv6; /* used for ipv6 addresses */
struct buffer str; /* used for char strings or buffers */
- struct meth meth; /* used for http method */
+ struct http_meth meth; /* used for http method */
};
/* Used to store sample constant */