]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: http: move the HTTP semantics definitions to http.h/http.c
authorWilly Tarreau <w@1wt.eu>
Mon, 10 Sep 2018 13:38:55 +0000 (15:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 11 Sep 2018 08:30:25 +0000 (10:30 +0200)
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).

23 files changed:
Makefile
include/common/buf.h
include/common/http.h [new file with mode: 0644]
include/proto/h1.h
include/proto/proto_http.h
include/types/hlua.h
include/types/proto_http.h
include/types/proxy.h
include/types/sample.h
src/checks.c
src/compression.c
src/flt_http_comp.c
src/h1.c
src/hlua_fcn.c
src/http.c [new file with mode: 0644]
src/lb_map.c
src/log.c
src/peers.c
src/proto_http.c
src/sample.c
src/session.c
src/stats.c
src/vars.c

index c49239958888b05ea2a4bcd3b6ced2be5da4bc22..d68d26368aedfd3582342fb3d4cdc9f7d6d2b2f6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -876,7 +876,7 @@ OBJS = src/proto_http.o src/cfgparse.o src/server.o src/stream.o        \
        src/sha1.o src/hpack-tbl.o src/hpack-enc.o src/uri_auth.o        \
        src/time.o src/proto_udp.o src/arg.o src/signal.o                \
        src/protocol.o src/lru.o src/hdr_idx.o src/hpack-huff.o          \
-       src/mailers.o src/h2.o src/base64.o src/hash.o
+       src/mailers.o src/h2.o src/base64.o src/hash.o src/http.o
 
 EBTREE_OBJS = $(EBTREE_DIR)/ebtree.o $(EBTREE_DIR)/eb32sctree.o \
               $(EBTREE_DIR)/eb32tree.o $(EBTREE_DIR)/eb64tree.o \
index a1355e653e66c07ff75aa7613fce3989624e7a20..420882026b45443c03d1f7615293a7acb8e5b352 100644 (file)
@@ -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 (file)
index 0000000..d283e29
--- /dev/null
@@ -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:
+ */
index eef310f8f6bb625e6dd823d753bf95dacd854cc5..299738330be2abae8bbdaf44cb5f839d89f0c58d 100644 (file)
 #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 @@ int h1_headers_to_hdr_list(char *start, const char *stop,
                            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.
  */
index 7849e154887adde35431e79b71e01f5c34124025..b537d45344eedd32c7b6a78ecea9c7b9554cd511 100644 (file)
  *   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 @@ struct redirect_rule *http_parse_redirect_rule(const char *file, int linenum, st
 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);
index 5a8173f3b018198fcc4bfc117c9ed0fb43ce8468..4fb63099dafbb7d7cc5ee2714e63ceddcfdf74d7 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <common/xref.h>
 
+#include <types/h1.h>
 #include <types/proxy.h>
 #include <types/server.h>
 
index 9c3905639298593be2de0d1656c210a238fbbe22..5cb05894477e7302bca51beb82315b74c9bc60b2 100644 (file)
@@ -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 @@ enum {
        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 @@ enum rule_result {
        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 @@ struct http_msg {
        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 @@ struct hdr_ctx {
        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 */
index 2d1b881965927bf0cafd977856658f2e91820f65..70bfeeef06fda799f6f2c7b97b66d15ca813a690 100644 (file)
@@ -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>
index 987a099a2857f3fc36a23165f6ed78b20f01a3eb..015c5ae881aff2c57797333545d716115d4a6323 100644 (file)
@@ -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 @@ enum {
 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 @@ union smp_ctx {
  * 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 */
index 28ee4c473c9e639d12a9640533816544d5f9d20c..b64d32e2072f1281381a9cc7a50bcca46a2ee774 100644 (file)
@@ -49,7 +49,6 @@
 #include <proto/mux_pt.h>
 #include <proto/queue.h>
 #include <proto/port_range.h>
-#include <proto/proto_http.h>
 #include <proto/proto_tcp.h>
 #include <proto/protocol.h>
 #include <proto/proxy.h>
index 3e98402db6f25a82a48f0c38db55db6a35c263cd..e7ce90a1f21416095fb1102240fd0ccf1b01f9af 100644 (file)
@@ -37,7 +37,6 @@
 #include <proto/acl.h>
 #include <proto/compression.h>
 #include <proto/freq_ctr.h>
-#include <proto/proto_http.h>
 #include <proto/stream.h>
 
 
index bf8f81ae5641d49eb465756dbcaaaf030948b05a..81e1b42443fceaf1c915a921fca40aa84b432176 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <types/compression.h>
 #include <types/filters.h>
-#include <types/proto_http.h>
+#include <types/h1.h>
 #include <types/proxy.h>
 #include <types/sample.h>
 
index 63ff99399be5bb07a76118448f7988543120e3ee..325f5b6c4358cdd164cf88c51b2a16c5549513f7 100644 (file)
--- a/src/h1.c
+++ b/src/h1.c
 #include <proto/h1.h>
 #include <proto/hdr_idx.h>
 
-/* It is about twice as fast on recent architectures to lookup a byte in a
- * table than to perform a boolean AND or OR between two tests. Refer to
- * RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
- * neither a separator nor a CTL char. An http ver_token is any ASCII which can
- * be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
- * digit. Note: please do not overwrite values in assignment since gcc-2.95
- * will not handle them correctly. It's worth noting that chars 128..255 are
- * nothing, not even control chars.
- */
-const unsigned char h1_char_classes[256] = {
-       [  0] = H1_FLG_CTL,
-       [  1] = H1_FLG_CTL,
-       [  2] = H1_FLG_CTL,
-       [  3] = H1_FLG_CTL,
-       [  4] = H1_FLG_CTL,
-       [  5] = H1_FLG_CTL,
-       [  6] = H1_FLG_CTL,
-       [  7] = H1_FLG_CTL,
-       [  8] = H1_FLG_CTL,
-       [  9] = H1_FLG_SPHT | H1_FLG_LWS | H1_FLG_SEP | H1_FLG_CTL,
-       [ 10] = H1_FLG_CRLF | H1_FLG_LWS | H1_FLG_CTL,
-       [ 11] = H1_FLG_CTL,
-       [ 12] = H1_FLG_CTL,
-       [ 13] = H1_FLG_CRLF | H1_FLG_LWS | H1_FLG_CTL,
-       [ 14] = H1_FLG_CTL,
-       [ 15] = H1_FLG_CTL,
-       [ 16] = H1_FLG_CTL,
-       [ 17] = H1_FLG_CTL,
-       [ 18] = H1_FLG_CTL,
-       [ 19] = H1_FLG_CTL,
-       [ 20] = H1_FLG_CTL,
-       [ 21] = H1_FLG_CTL,
-       [ 22] = H1_FLG_CTL,
-       [ 23] = H1_FLG_CTL,
-       [ 24] = H1_FLG_CTL,
-       [ 25] = H1_FLG_CTL,
-       [ 26] = H1_FLG_CTL,
-       [ 27] = H1_FLG_CTL,
-       [ 28] = H1_FLG_CTL,
-       [ 29] = H1_FLG_CTL,
-       [ 30] = H1_FLG_CTL,
-       [ 31] = H1_FLG_CTL,
-       [' '] = H1_FLG_SPHT | H1_FLG_LWS | H1_FLG_SEP,
-       ['!'] = H1_FLG_TOK,
-       ['"'] = H1_FLG_SEP,
-       ['#'] = H1_FLG_TOK,
-       ['$'] = H1_FLG_TOK,
-       ['%'] = H1_FLG_TOK,
-       ['&'] = H1_FLG_TOK,
-       [ 39] = H1_FLG_TOK,
-       ['('] = H1_FLG_SEP,
-       [')'] = H1_FLG_SEP,
-       ['*'] = H1_FLG_TOK,
-       ['+'] = H1_FLG_TOK,
-       [','] = H1_FLG_SEP,
-       ['-'] = H1_FLG_TOK,
-       ['.'] = H1_FLG_TOK | H1_FLG_VER,
-       ['/'] = H1_FLG_SEP | H1_FLG_VER,
-       ['0'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['1'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['2'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['3'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['4'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['5'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['6'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['7'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['8'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       ['9'] = H1_FLG_TOK | H1_FLG_VER | H1_FLG_DIG,
-       [':'] = H1_FLG_SEP,
-       [';'] = H1_FLG_SEP,
-       ['<'] = H1_FLG_SEP,
-       ['='] = H1_FLG_SEP,
-       ['>'] = H1_FLG_SEP,
-       ['?'] = H1_FLG_SEP,
-       ['@'] = H1_FLG_SEP,
-       ['A'] = H1_FLG_TOK,
-       ['B'] = H1_FLG_TOK,
-       ['C'] = H1_FLG_TOK,
-       ['D'] = H1_FLG_TOK,
-       ['E'] = H1_FLG_TOK,
-       ['F'] = H1_FLG_TOK,
-       ['G'] = H1_FLG_TOK,
-       ['H'] = H1_FLG_TOK | H1_FLG_VER,
-       ['I'] = H1_FLG_TOK,
-       ['J'] = H1_FLG_TOK,
-       ['K'] = H1_FLG_TOK,
-       ['L'] = H1_FLG_TOK,
-       ['M'] = H1_FLG_TOK,
-       ['N'] = H1_FLG_TOK,
-       ['O'] = H1_FLG_TOK,
-       ['P'] = H1_FLG_TOK | H1_FLG_VER,
-       ['Q'] = H1_FLG_TOK,
-       ['R'] = H1_FLG_TOK | H1_FLG_VER,
-       ['S'] = H1_FLG_TOK | H1_FLG_VER,
-       ['T'] = H1_FLG_TOK | H1_FLG_VER,
-       ['U'] = H1_FLG_TOK,
-       ['V'] = H1_FLG_TOK,
-       ['W'] = H1_FLG_TOK,
-       ['X'] = H1_FLG_TOK,
-       ['Y'] = H1_FLG_TOK,
-       ['Z'] = H1_FLG_TOK,
-       ['['] = H1_FLG_SEP,
-       [ 92] = H1_FLG_SEP,
-       [']'] = H1_FLG_SEP,
-       ['^'] = H1_FLG_TOK,
-       ['_'] = H1_FLG_TOK,
-       ['`'] = H1_FLG_TOK,
-       ['a'] = H1_FLG_TOK,
-       ['b'] = H1_FLG_TOK,
-       ['c'] = H1_FLG_TOK,
-       ['d'] = H1_FLG_TOK,
-       ['e'] = H1_FLG_TOK,
-       ['f'] = H1_FLG_TOK,
-       ['g'] = H1_FLG_TOK,
-       ['h'] = H1_FLG_TOK,
-       ['i'] = H1_FLG_TOK,
-       ['j'] = H1_FLG_TOK,
-       ['k'] = H1_FLG_TOK,
-       ['l'] = H1_FLG_TOK,
-       ['m'] = H1_FLG_TOK,
-       ['n'] = H1_FLG_TOK,
-       ['o'] = H1_FLG_TOK,
-       ['p'] = H1_FLG_TOK,
-       ['q'] = H1_FLG_TOK,
-       ['r'] = H1_FLG_TOK,
-       ['s'] = H1_FLG_TOK,
-       ['t'] = H1_FLG_TOK,
-       ['u'] = H1_FLG_TOK,
-       ['v'] = H1_FLG_TOK,
-       ['w'] = H1_FLG_TOK,
-       ['x'] = H1_FLG_TOK,
-       ['y'] = H1_FLG_TOK,
-       ['z'] = H1_FLG_TOK,
-       ['{'] = H1_FLG_SEP,
-       ['|'] = H1_FLG_TOK,
-       ['}'] = H1_FLG_SEP,
-       ['~'] = H1_FLG_TOK,
-       [127] = H1_FLG_CTL,
-};
-
-
 /*
  * This function parses a status line between <ptr> and <end>, starting with
  * parser state <state>. Only states HTTP_MSG_RPVER, HTTP_MSG_RPVER_SP,
index cebce2244490623ed71338ad68cfb9dfb64f4db2..57214455fc9192b1f2e54d1446fc6786f43207e0 100644 (file)
@@ -26,7 +26,7 @@
 #include <types/proxy.h>
 #include <types/stats.h>
 
-#include <proto/proto_http.h>
+#include <proto/h1.h>
 #include <proto/proxy.h>
 #include <proto/server.h>
 #include <proto/stats.h>
diff --git a/src/http.c b/src/http.c
new file mode 100644 (file)
index 0000000..ad620a9
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * HTTP semantics
+ *
+ * Copyright 2000-2018 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <ctype.h>
+#include <common/config.h>
+#include <common/http.h>
+
+/* It is about twice as fast on recent architectures to lookup a byte in a
+ * table than to perform a boolean AND or OR between two tests. Refer to
+ * RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
+ * neither a separator nor a CTL char. An http ver_token is any ASCII which can
+ * be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
+ * digit. Note: please do not overwrite values in assignment since gcc-2.95
+ * will not handle them correctly. It's worth noting that chars 128..255 are
+ * nothing, not even control chars.
+ */
+const unsigned char http_char_classes[256] = {
+       [  0] = HTTP_FLG_CTL,
+       [  1] = HTTP_FLG_CTL,
+       [  2] = HTTP_FLG_CTL,
+       [  3] = HTTP_FLG_CTL,
+       [  4] = HTTP_FLG_CTL,
+       [  5] = HTTP_FLG_CTL,
+       [  6] = HTTP_FLG_CTL,
+       [  7] = HTTP_FLG_CTL,
+       [  8] = HTTP_FLG_CTL,
+       [  9] = HTTP_FLG_SPHT | HTTP_FLG_LWS | HTTP_FLG_SEP | HTTP_FLG_CTL,
+       [ 10] = HTTP_FLG_CRLF | HTTP_FLG_LWS | HTTP_FLG_CTL,
+       [ 11] = HTTP_FLG_CTL,
+       [ 12] = HTTP_FLG_CTL,
+       [ 13] = HTTP_FLG_CRLF | HTTP_FLG_LWS | HTTP_FLG_CTL,
+       [ 14] = HTTP_FLG_CTL,
+       [ 15] = HTTP_FLG_CTL,
+       [ 16] = HTTP_FLG_CTL,
+       [ 17] = HTTP_FLG_CTL,
+       [ 18] = HTTP_FLG_CTL,
+       [ 19] = HTTP_FLG_CTL,
+       [ 20] = HTTP_FLG_CTL,
+       [ 21] = HTTP_FLG_CTL,
+       [ 22] = HTTP_FLG_CTL,
+       [ 23] = HTTP_FLG_CTL,
+       [ 24] = HTTP_FLG_CTL,
+       [ 25] = HTTP_FLG_CTL,
+       [ 26] = HTTP_FLG_CTL,
+       [ 27] = HTTP_FLG_CTL,
+       [ 28] = HTTP_FLG_CTL,
+       [ 29] = HTTP_FLG_CTL,
+       [ 30] = HTTP_FLG_CTL,
+       [ 31] = HTTP_FLG_CTL,
+       [' '] = HTTP_FLG_SPHT | HTTP_FLG_LWS | HTTP_FLG_SEP,
+       ['!'] = HTTP_FLG_TOK,
+       ['"'] = HTTP_FLG_SEP,
+       ['#'] = HTTP_FLG_TOK,
+       ['$'] = HTTP_FLG_TOK,
+       ['%'] = HTTP_FLG_TOK,
+       ['&'] = HTTP_FLG_TOK,
+       [ 39] = HTTP_FLG_TOK,
+       ['('] = HTTP_FLG_SEP,
+       [')'] = HTTP_FLG_SEP,
+       ['*'] = HTTP_FLG_TOK,
+       ['+'] = HTTP_FLG_TOK,
+       [','] = HTTP_FLG_SEP,
+       ['-'] = HTTP_FLG_TOK,
+       ['.'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['/'] = HTTP_FLG_SEP | HTTP_FLG_VER,
+       ['0'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['1'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['2'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['3'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['4'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['5'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['6'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['7'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['8'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       ['9'] = HTTP_FLG_TOK | HTTP_FLG_VER | HTTP_FLG_DIG,
+       [':'] = HTTP_FLG_SEP,
+       [';'] = HTTP_FLG_SEP,
+       ['<'] = HTTP_FLG_SEP,
+       ['='] = HTTP_FLG_SEP,
+       ['>'] = HTTP_FLG_SEP,
+       ['?'] = HTTP_FLG_SEP,
+       ['@'] = HTTP_FLG_SEP,
+       ['A'] = HTTP_FLG_TOK,
+       ['B'] = HTTP_FLG_TOK,
+       ['C'] = HTTP_FLG_TOK,
+       ['D'] = HTTP_FLG_TOK,
+       ['E'] = HTTP_FLG_TOK,
+       ['F'] = HTTP_FLG_TOK,
+       ['G'] = HTTP_FLG_TOK,
+       ['H'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['I'] = HTTP_FLG_TOK,
+       ['J'] = HTTP_FLG_TOK,
+       ['K'] = HTTP_FLG_TOK,
+       ['L'] = HTTP_FLG_TOK,
+       ['M'] = HTTP_FLG_TOK,
+       ['N'] = HTTP_FLG_TOK,
+       ['O'] = HTTP_FLG_TOK,
+       ['P'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['Q'] = HTTP_FLG_TOK,
+       ['R'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['S'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['T'] = HTTP_FLG_TOK | HTTP_FLG_VER,
+       ['U'] = HTTP_FLG_TOK,
+       ['V'] = HTTP_FLG_TOK,
+       ['W'] = HTTP_FLG_TOK,
+       ['X'] = HTTP_FLG_TOK,
+       ['Y'] = HTTP_FLG_TOK,
+       ['Z'] = HTTP_FLG_TOK,
+       ['['] = HTTP_FLG_SEP,
+       [ 92] = HTTP_FLG_SEP,
+       [']'] = HTTP_FLG_SEP,
+       ['^'] = HTTP_FLG_TOK,
+       ['_'] = HTTP_FLG_TOK,
+       ['`'] = HTTP_FLG_TOK,
+       ['a'] = HTTP_FLG_TOK,
+       ['b'] = HTTP_FLG_TOK,
+       ['c'] = HTTP_FLG_TOK,
+       ['d'] = HTTP_FLG_TOK,
+       ['e'] = HTTP_FLG_TOK,
+       ['f'] = HTTP_FLG_TOK,
+       ['g'] = HTTP_FLG_TOK,
+       ['h'] = HTTP_FLG_TOK,
+       ['i'] = HTTP_FLG_TOK,
+       ['j'] = HTTP_FLG_TOK,
+       ['k'] = HTTP_FLG_TOK,
+       ['l'] = HTTP_FLG_TOK,
+       ['m'] = HTTP_FLG_TOK,
+       ['n'] = HTTP_FLG_TOK,
+       ['o'] = HTTP_FLG_TOK,
+       ['p'] = HTTP_FLG_TOK,
+       ['q'] = HTTP_FLG_TOK,
+       ['r'] = HTTP_FLG_TOK,
+       ['s'] = HTTP_FLG_TOK,
+       ['t'] = HTTP_FLG_TOK,
+       ['u'] = HTTP_FLG_TOK,
+       ['v'] = HTTP_FLG_TOK,
+       ['w'] = HTTP_FLG_TOK,
+       ['x'] = HTTP_FLG_TOK,
+       ['y'] = HTTP_FLG_TOK,
+       ['z'] = HTTP_FLG_TOK,
+       ['{'] = HTTP_FLG_SEP,
+       ['|'] = HTTP_FLG_TOK,
+       ['}'] = HTTP_FLG_SEP,
+       ['~'] = HTTP_FLG_TOK,
+       [127] = HTTP_FLG_CTL,
+};
+
+const struct ist http_known_methods[HTTP_METH_OTHER] = {
+       [HTTP_METH_OPTIONS] = IST("OPTIONS"),
+       [HTTP_METH_GET]     = IST("GET"),
+       [HTTP_METH_HEAD]    = IST("HEAD"),
+       [HTTP_METH_POST]    = IST("POST"),
+       [HTTP_METH_PUT]     = IST("PUT"),
+       [HTTP_METH_DELETE]  = IST("DELETE"),
+       [HTTP_METH_TRACE]   = IST("TRACE"),
+       [HTTP_METH_CONNECT] = IST("CONNECT"),
+};
+
+/*
+ * returns a known method among HTTP_METH_* or HTTP_METH_OTHER for all unknown
+ * ones.
+ */
+enum http_meth_t find_http_meth(const char *str, const int len)
+{
+       const struct ist m = ist2(str, len);
+
+       if      (isteq(m, ist("GET")))     return HTTP_METH_GET;
+       else if (isteq(m, ist("HEAD")))    return HTTP_METH_HEAD;
+       else if (isteq(m, ist("POST")))    return HTTP_METH_POST;
+       else if (isteq(m, ist("CONNECT"))) return HTTP_METH_CONNECT;
+       else if (isteq(m, ist("PUT")))     return HTTP_METH_PUT;
+       else if (isteq(m, ist("OPTIONS"))) return HTTP_METH_OPTIONS;
+       else if (isteq(m, ist("DELETE")))  return HTTP_METH_DELETE;
+       else if (isteq(m, ist("TRACE")))   return HTTP_METH_TRACE;
+       else                               return HTTP_METH_OTHER;
+}
index 54569b0a27b2ea892c29fe0cd1d15fc523c97262..2d8faa9ae5c4f04664b4f81f826b5075404fc004 100644 (file)
@@ -20,8 +20,6 @@
 
 #include <proto/backend.h>
 #include <proto/lb_map.h>
-#include <proto/proto_http.h>
-#include <proto/proto_tcp.h>
 #include <proto/queue.h>
 
 /* this function updates the map according to server <srv>'s new state.
index 3bd22858337facb56f39363791a07cb4515ee11b..11e75ec415da5227f0cdb44744e395e0fea69756 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -36,7 +36,7 @@
 #include <proto/applet.h>
 #include <proto/cli.h>
 #include <proto/frontend.h>
-#include <proto/proto_http.h>
+#include <proto/h1.h>
 #include <proto/log.h>
 #include <proto/sample.h>
 #include <proto/stream.h>
index 1fefa9431c4338b6ec1a50c616aca73ffefcba80..50aee870dbe861a19599c53cd1213f4e34574f0a 100644 (file)
@@ -39,8 +39,6 @@
 #include <proto/log.h>
 #include <proto/hdr_idx.h>
 #include <proto/mux_pt.h>
-#include <proto/proto_tcp.h>
-#include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/session.h>
 #include <proto/stream.h>
index b97c6bf38bd50055f557668f56e5e5a5ce779a97..b153b141333731172437c7bfcbf0b0bfd4141b81 100644 (file)
@@ -487,55 +487,6 @@ void init_proto_http()
        pool_head_uniqueid = create_pool("uniqueid", UNIQUEID_LEN, MEM_F_SHARED);
 }
 
-/*
- * We have 26 list of methods (1 per first letter), each of which can have
- * up to 3 entries (2 valid, 1 null).
- */
-struct http_method_desc {
-       enum http_meth_t meth;
-       int len;
-       const char text[8];
-};
-
-const struct http_method_desc http_methods[26][3] = {
-       ['C' - 'A'] = {
-               [0] = { .meth = HTTP_METH_CONNECT , .len=7, .text="CONNECT" },
-       },
-       ['D' - 'A'] = {
-               [0] = { .meth = HTTP_METH_DELETE  , .len=6, .text="DELETE"  },
-       },
-       ['G' - 'A'] = {
-               [0] = { .meth = HTTP_METH_GET     , .len=3, .text="GET"     },
-       },
-       ['H' - 'A'] = {
-               [0] = { .meth = HTTP_METH_HEAD    , .len=4, .text="HEAD"    },
-       },
-       ['O' - 'A'] = {
-               [0] = { .meth = HTTP_METH_OPTIONS , .len=7, .text="OPTIONS" },
-       },
-       ['P' - 'A'] = {
-               [0] = { .meth = HTTP_METH_POST    , .len=4, .text="POST"    },
-               [1] = { .meth = HTTP_METH_PUT     , .len=3, .text="PUT"     },
-       },
-       ['T' - 'A'] = {
-               [0] = { .meth = HTTP_METH_TRACE   , .len=5, .text="TRACE"   },
-       },
-       /* rest is empty like this :
-        *      [0] = { .meth = HTTP_METH_OTHER   , .len=0, .text=""        },
-        */
-};
-
-const struct http_method_name http_known_methods[HTTP_METH_OTHER] = {
-       [HTTP_METH_OPTIONS] = { "OPTIONS",  7 },
-       [HTTP_METH_GET]     = { "GET",      3 },
-       [HTTP_METH_HEAD]    = { "HEAD",     4 },
-       [HTTP_METH_POST]    = { "POST",     4 },
-       [HTTP_METH_PUT]     = { "PUT",      3 },
-       [HTTP_METH_DELETE]  = { "DELETE",   6 },
-       [HTTP_METH_TRACE]   = { "TRACE",    5 },
-       [HTTP_METH_CONNECT] = { "CONNECT",  7 },
-};
-
 /*
  * Adds a header and its CRLF at the tail of the message's buffer, just before
  * the last CRLF.
@@ -959,28 +910,6 @@ http_reply_and_close(struct stream *s, short status, struct buffer *msg)
        stream_int_retnclose(&s->si[0], msg);
 }
 
-/*
- * returns a known method among HTTP_METH_* or HTTP_METH_OTHER for all unknown
- * ones.
- */
-enum http_meth_t find_http_meth(const char *str, const int len)
-{
-       unsigned char m;
-       const struct http_method_desc *h;
-
-       m = ((unsigned)*str - 'A');
-
-       if (m < 26) {
-               for (h = http_methods[m]; h->len > 0; h++) {
-                       if (unlikely(h->len != len))
-                               continue;
-                       if (likely(memcmp(str, h->text, h->len) == 0))
-                               return h->meth;
-               };
-       }
-       return HTTP_METH_OTHER;
-}
-
 /* Parse the URI from the given transaction (which is assumed to be in request
  * phase) and look for the "/" beginning the PATH. If not found, return NULL.
  * It is returned otherwise.
index e3dea1bf43c6e92844dc15f6fac27b40299b48d9..138390d9db8dc9f486323dd0ba8225f4ec72d2c0 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <common/chunk.h>
 #include <common/hash.h>
+#include <common/http.h>
 #include <common/standard.h>
 #include <common/uri_auth.h>
 #include <common/base64.h>
@@ -27,7 +28,6 @@
 #include <proto/arg.h>
 #include <proto/auth.h>
 #include <proto/log.h>
-#include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/sample.h>
 #include <proto/stick_table.h>
@@ -749,7 +749,7 @@ static int c_meth2str(struct sample *smp)
        else if (smp->data.u.meth.meth < HTTP_METH_OTHER) {
                /* The method is known, copy the pointer containing the string. */
                meth = smp->data.u.meth.meth;
-               smp->data.u.str.area = http_known_methods[meth].name;
+               smp->data.u.str.area = http_known_methods[meth].ptr;
                smp->data.u.str.data = http_known_methods[meth].len;
                smp->flags |= SMP_F_CONST;
                smp->data.type = SMP_T_STR;
index c9d50df5b76eaca47320b245a8cb8a7e0ddd9b1b..3454925ad9068d9d5e7ca96784c7fee2fc7f7d6c 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/config.h>
 #include <common/buffer.h>
 #include <common/debug.h>
+#include <common/http.h>
 #include <common/memory.h>
 
 #include <types/global.h>
@@ -21,7 +22,6 @@
 #include <proto/connection.h>
 #include <proto/listener.h>
 #include <proto/log.h>
-#include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/session.h>
 #include <proto/stream.h>
index 4cea7768613a8f670724bb421700e7e1df2444a1..da960f5c9d8f1fd2d0d8d437e70fba71ed0fdcfe 100644 (file)
@@ -28,6 +28,7 @@
 #include <common/compat.h>
 #include <common/config.h>
 #include <common/debug.h>
+#include <common/http.h>
 #include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
@@ -57,7 +58,6 @@
 #include <proto/pipe.h>
 #include <proto/listener.h>
 #include <proto/map.h>
-#include <proto/proto_http.h>
 #include <proto/proxy.h>
 #include <proto/sample.h>
 #include <proto/session.h>
index 5787cf6edda223d3987874aaacb2c0f20d33a236..905e20c4f2eeb6efd85db2f909aec491b2a5d31a 100644 (file)
@@ -1,6 +1,7 @@
 #include <ctype.h>
 
 #include <common/cfgparse.h>
+#include <common/http.h>
 #include <common/mini-clist.h>
 
 #include <types/vars.h>