]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] http redirect: add the ability to append a '/' to the URL
authorWilly Tarreau <w@1wt.eu>
Sat, 9 Jan 2010 23:42:19 +0000 (00:42 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 28 Jan 2010 22:16:37 +0000 (23:16 +0100)
Sometimes it can be desired to return a location which is the same
as the request with a slash appended when there was not one in the
request. A typical use of this is for sending a 301 so that people
don't reference links without the trailing slash. The name of the
new option is "append-slash" and it can be used on "redirect"
statements in prefix mode.

(cherry picked from commit 81e3b4f48d168da55c7902d51bb71212f2a817d6)

doc/configuration.txt
include/types/proto_http.h
src/cfgparse.c
src/proto_http.c

index 7ccc09c84d23333c12d8042b8c63fd8b94acb391..40907cad03b4d65c3f2ce9323fdafeb64b0aa58b 100644 (file)
@@ -3004,6 +3004,12 @@ redirect prefix   <to> [code <code>] <option> {if | unless} <condition>
         for directing users to a non-secure page for instance. It has no effect
         with a location-type redirect.
 
+      - "append-slash"
+        This keyword may be used in conjunction with "drop-query" to redirect
+        users who use a URL not ending with a '/' to the same one with the '/'.
+        It can be useful to ensure that search engines will only see one URL.
+        For this, a return code 301 is preferred.
+
       - "set-cookie NAME[=value]"
         A "Set-Cookie" header will be added with NAME (and optionally "=value")
         to the response. This is sometimes used to indicate that a user has
@@ -3034,6 +3040,10 @@ redirect prefix   <to> [code <code>] <option> {if | unless} <condition>
         redirect location http://mysite.com/           if !login_page secure
         redirect location / clear-cookie USERID=       if logout
 
+  Example: send redirects for request for articles without a '/'.
+        acl missing_slash path_reg ^/article/[^/]*$
+        redirect code 301 prefix / drop-query append-slash if missing_slash
+
   See section 7 about ACL usage.
 
 
index c0350d2458f23fb16be8071705d1e031259cd45f..6ecfe1ee8ded000474935c0ba708c7d294c5ad72 100644 (file)
@@ -169,6 +169,7 @@ enum {
 enum {
        REDIRECT_FLAG_NONE = 0,
        REDIRECT_FLAG_DROP_QS = 1,      /* drop query string */
+       REDIRECT_FLAG_APPEND_SLASH = 2, /* append a slash if missing at the end */
 };
 
 /* Redirect types (location, prefix, extended ) */
index 3b99bfb13b3d2d970ece740ec1c16cdf189ac70f..534e1d164ccbf732ed12f2d9dc14917fe2e6fe6c 100644 (file)
@@ -1596,6 +1596,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                        else if (!strcmp(args[cur_arg],"drop-query")) {
                                flags |= REDIRECT_FLAG_DROP_QS;
                        }
+                       else if (!strcmp(args[cur_arg],"append-slash")) {
+                               flags |= REDIRECT_FLAG_APPEND_SLASH;
+                       }
                        else if (!strcmp(args[cur_arg], "if")) {
                                pol = ACL_COND_IF;
                                cur_arg++;
@@ -1607,7 +1610,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
                                break;
                        }
                        else {
-                               Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie' or 'drop-query' (was '%s').\n",
+                               Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', '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;
index e656a29f90ae37bd12526408c8b0d1e3720db732..2364bea309e0ca298593b8688cffde40049f2fbc 100644 (file)
@@ -2005,6 +2005,16 @@ int http_process_request(struct session *s, struct buffer *req)
                                        /* 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 > sizeof(trash) - 5)
+                                                       goto return_bad_req;
+                                               rdr.str[rdr.len] = '/';
+                                               rdr.len++;
+                                       }
+
                                        break;
                                }
                                case REDIRECT_TYPE_LOCATION: