package: haproxy - [PATCH 10/10] MEDIUM: http: add "redirect scheme" to ease HTTP to
authorheil <heil@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Fri, 29 Nov 2013 15:28:24 +0000 (15:28 +0000)
committerheil <heil@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Fri, 29 Nov 2013 15:28:24 +0000 (15:28 +0000)
 HTTPS redirection

git-svn-id: svn://svn.openwrt.org/openwrt/packages@38945 3c298f89-4303-0410-b956-a3cf2f4a3e73

net/haproxy/Makefile
net/haproxy/patches/0010-MEDIUM-http-add-redirect-scheme-to-ease-HTTP-to-HTTP.patch [new file with mode: 0644]

index 3fea8b4..e7a1d87 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
 PKG_VERSION:=1.4.24
-PKG_RELEASE:=09
+PKG_RELEASE:=10
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src
diff --git a/net/haproxy/patches/0010-MEDIUM-http-add-redirect-scheme-to-ease-HTTP-to-HTTP.patch b/net/haproxy/patches/0010-MEDIUM-http-add-redirect-scheme-to-ease-HTTP-to-HTTP.patch
new file mode 100644 (file)
index 0000000..53863c5
--- /dev/null
@@ -0,0 +1,202 @@
+From eb9632f7c6ae675bdee4c82eb0d298ba7f37fc52 Mon Sep 17 00:00:00 2001
+From: Willy Tarreau <w@1wt.eu>
+Date: Wed, 12 Sep 2012 08:43:15 +0200
+Subject: [PATCH 10/10] MEDIUM: http: add "redirect scheme" to ease HTTP to
+ HTTPS redirection
+
+For instance :
+
+   redirect scheme https if !{ is_ssl }
+
+Backport-suggested-by: Russell Geldmacher <russell.geldmacher@gmail.com>
+(cherry picked from commit 2e1dca8f5238155cbc52d37316fe858c4f61cf34)
+---
+ doc/configuration.txt      | 35 ++++++++++++++++++-------
+ include/types/proto_http.h |  1 +
+ src/cfgparse.c             | 14 +++++++++-
+ src/proto_http.c           | 65 ++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 104 insertions(+), 11 deletions(-)
+
+diff --git a/doc/configuration.txt b/doc/configuration.txt
+index 56438dd..f2043a1 100644
+--- a/doc/configuration.txt
++++ b/doc/configuration.txt
+@@ -4039,8 +4039,9 @@ rate-limit sessions <rate>
+   See also : the "backlog" keyword and the "fe_sess_rate" ACL criterion.
+-redirect location <to> [code <code>] <option> [{if | unless} <condition>]
+-redirect prefix   <to> [code <code>] <option> [{if | unless} <condition>]
++redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
++redirect prefix   <pfx> [code <code>] <option> [{if | unless} <condition>]
++redirect scheme   <sch> [code <code>] <option> [{if | unless} <condition>]
+   Return an HTTP redirection if/unless a condition is matched
+   May be used in sections :   defaults | frontend | listen | backend
+                                  no    |    yes   |   yes  |   yes
+@@ -4049,14 +4050,25 @@ redirect prefix   <to> [code <code>] <option> [{if | unless} <condition>]
+   response. If no condition is specified, the redirect applies unconditionally.
+   Arguments :
+-    <to>      With "redirect location", the exact value in <to> is placed into
+-              the HTTP "Location" header. In case of "redirect prefix", the
+-              "Location" header is built from the concatenation of <to> and the
+-              complete URI, including the query string, unless the "drop-query"
+-              option is specified (see below). As a special case, if <to>
+-              equals exactly "/" in prefix mode, then nothing is inserted
+-              before the original URI. It allows one to redirect to the same
+-              URL.
++    <loc>     With "redirect location", the exact value in <loc> is placed into
++              the HTTP "Location" header.
++
++    <pfx>     With "redirect prefix", the "Location" header is built from the
++              concatenation of <pfx> and the complete URI path, including the
++              query string, unless the "drop-query" option is specified (see
++              below). As a special case, if <pfx> equals exactly "/", then
++              nothing is inserted before the original URI. It allows one to
++              redirect to the same URL (for instance, to insert a cookie).
++
++    <sch>     With "redirect scheme", then the "Location" header is built by
++              concatenating <sch> with "://" then the first occurrence of the
++              "Host" header, and then the URI path, including the query string
++              unless the "drop-query" option is specified (see below). If no
++              path is found or if the path is "*", then "/" is used instead. If
++              no "Host" header is found, then an empty host component will be
++              returned, which most recent browsers interprete as redirecting to
++              the same host. This directive is mostly used to redirect HTTP to
++              HTTPS.
+     <code>    The code is optional. It indicates which type of HTTP redirection
+               is desired. Only codes 301, 302, 303, 307 and 308 are supported,
+@@ -4117,6 +4129,9 @@ redirect prefix   <to> [code <code>] <option> [{if | unless} <condition>]
+         acl missing_slash path_reg ^/article/[^/]*$
+         redirect code 301 prefix / drop-query append-slash if missing_slash
++  Example: redirect all HTTP traffic to HTTPS when SSL is handled by haproxy.
++        redirect scheme https if !{ is_ssl }
++
+   See section 7 about ACL usage.
+diff --git a/include/types/proto_http.h b/include/types/proto_http.h
+index 09d4dd8..0e2b14f 100644
+--- a/include/types/proto_http.h
++++ b/include/types/proto_http.h
+@@ -224,6 +224,7 @@ enum {
+       REDIRECT_TYPE_NONE = 0,         /* no redirection */
+       REDIRECT_TYPE_LOCATION,         /* location redirect */
+       REDIRECT_TYPE_PREFIX,           /* prefix redirect */
++      REDIRECT_TYPE_SCHEME,           /* scheme redirect (eg: switch from http to https) */
+ };
+ /* Perist types (force-persist, ignore-persist) */
+diff --git a/src/cfgparse.c b/src/cfgparse.c
+index cecec03..09ffcd3 100644
+--- a/src/cfgparse.c
++++ b/src/cfgparse.c
+@@ -2182,6 +2182,18 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
+                               cur_arg++;
+                               destination = args[cur_arg];
+                       }
++                      else if (!strcmp(args[cur_arg], "scheme")) {
++                              if (!*args[cur_arg + 1]) {
++                                      Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
++                                            file, linenum, args[0], args[cur_arg]);
++                                      err_code |= ERR_ALERT | ERR_FATAL;
++                                      goto out;
++                              }
++
++                              type = REDIRECT_TYPE_SCHEME;
++                              cur_arg++;
++                              destination = args[cur_arg];
++                      }
+                       else if (!strcmp(args[cur_arg], "set-cookie")) {
+                               if (!*args[cur_arg + 1]) {
+                                       Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
+@@ -2240,7 +2252,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
+                               break;
+                       }
+                       else {
+-                              Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
++                              Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
+                                     file, linenum, args[0], args[cur_arg]);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto out;
+diff --git a/src/proto_http.c b/src/proto_http.c
+index 7fd1fe6..ed35795 100644
+--- a/src/proto_http.c
++++ b/src/proto_http.c
+@@ -3390,6 +3390,71 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
+                               goto return_bad_req;
+                       switch(rule->type) {
++                      case REDIRECT_TYPE_SCHEME: {
++                              const char *path;
++                              const char *host;
++                              struct hdr_ctx ctx;
++                              int pathlen;
++                              int hostlen;
++
++                              host = "";
++                              hostlen = 0;
++                              ctx.idx = 0;
++                              if (http_find_header2("Host", 4, msg->sol, &txn->hdr_idx, &ctx)) {
++                                      host = ctx.line + ctx.val;
++                                      hostlen = ctx.vlen;
++                              }
++
++                              path = http_get_path(txn);
++                              /* build message using path */
++                              if (path) {
++                                      pathlen = txn->req.sl.rq.u_l + (txn->req.sol + txn->req.sl.rq.u) - path;
++                                      if (rule->flags & REDIRECT_FLAG_DROP_QS) {
++                                              int qs = 0;
++                                              while (qs < pathlen) {
++                                                      if (path[qs] == '?') {
++                                                              pathlen = qs;
++                                                              break;
++                                                      }
++                                                      qs++;
++                                              }
++                                      }
++                              } else {
++                                      path = "/";
++                                      pathlen = 1;
++                              }
++
++                              /* check if we can add scheme + "://" + host + path */
++                              if (rdr.len + rule->rdr_len + 3 + hostlen + pathlen > rdr.size - 4)
++                                      goto return_bad_req;
++
++                              /* add scheme */
++                              memcpy(rdr.str + rdr.len, rule->rdr_str, rule->rdr_len);
++                              rdr.len += rule->rdr_len;
++
++                              /* add "://" */
++                              memcpy(rdr.str + rdr.len, "://", 3);
++                              rdr.len += 3;
++
++                              /* add host */
++                              memcpy(rdr.str + rdr.len, host, hostlen);
++                              rdr.len += hostlen;
++
++                              /* add path */
++                              memcpy(rdr.str + rdr.len, path, pathlen);
++                              rdr.len += pathlen;
++
++                              /* append a slash at the end of the location is needed and missing */
++                              if (rdr.len && rdr.str[rdr.len - 1] != '/' &&
++                                  (rule->flags & REDIRECT_FLAG_APPEND_SLASH)) {
++                                      if (rdr.len > rdr.size - 5)
++                                              goto return_bad_req;
++                                      rdr.str[rdr.len] = '/';
++                                      rdr.len++;
++                              }
++
++                              break;
++                      }
+                       case REDIRECT_TYPE_PREFIX: {
+                               const char *path;
+                               int pathlen;
+-- 
+1.8.1.5
+