]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] Stats: add support for the HEAD method
authorWilly Tarreau <w@1wt.eu>
Sun, 7 Jan 2007 12:47:30 +0000 (13:47 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 7 Jan 2007 12:47:30 +0000 (13:47 +0100)
There are browsers which sometimes send HEAD requests to the stats
page, but it was not handled so it returned a 503 server error or
was simply sent to the default backend servers.

Now with a HEAD request, the stats return the headers and finish
there. Normally, other methods should be blocked so that the stats
page really catches the whole URI. Other methods would need to cause
a 405 Method not allowed to be returned.

src/proto_http.c

index b5f974a4495906f8756803c9cae75cdc8658a6f8..f66083121cb85cbf73a7c404f1e0702c66ff57ed 100644 (file)
@@ -1097,7 +1097,8 @@ int process_cli(struct session *t)
                                        goto return_bad_req;
                        }
 
-                       if (rule_set->uri_auth != NULL && t->hreq.meth == HTTP_METH_GET) {
+                       if (rule_set->uri_auth != NULL &&
+                           (t->hreq.meth == HTTP_METH_GET || t->hreq.meth == HTTP_METH_HEAD)) {
                                /* we have to check the URI and auth for this request */
                                if (stats_check_uri_auth(t, rule_set))
                                        return 1;
@@ -2822,6 +2823,13 @@ int produce_content_stats(struct session *s)
                if (!(s->flags & SN_FINST_MASK))
                        s->flags |= SN_FINST_R;
 
+               if (s->hreq.meth == HTTP_METH_HEAD) {
+                       /* that's all we return in case of HEAD request */
+                       s->data_state = DATA_ST_FIN;
+                       s->flags &= ~SN_SELF_GEN;
+                       return 1;
+               }
+
                s->data_state = DATA_ST_HEAD; /* let's start producing data */
                /* fall through */
 
@@ -2985,7 +2993,7 @@ int produce_content_stats(struct session *s)
                /* fall through */
 
        case DATA_ST_END:
-               chunk_printf(&msg, sizeof(trash), "</body></html>");
+               chunk_printf(&msg, sizeof(trash), "</body></html>\n");
                if (buffer_write_chunk(rep, &msg) != 0)
                        return 0;
 
@@ -3841,12 +3849,12 @@ void get_srv_from_appsession(struct session *t, const char *begin, const char *e
 
 
 /*
- * In a GET request, check if the requested URI matches the stats uri for the
- * current backend, and if an authorization has been passed and is valid.
+ * In a GET or HEAD request, check if the requested URI matches the stats uri
+ * for the current backend, and if an authorization has been passed and is valid.
  *
- * It is assumed that the request is a GET and that the t->be->fiprm->uri_auth field
- * is valid. An HTTP/401 response may be sent, or produce_content() can be
- * called to start sending data.
+ * It is assumed that the request is either a HEAD or GET and that the
+ * t->be->fiprm->uri_auth field is valid. An HTTP/401 response may be sent, or
+ * produce_content() can be called to start sending data.
  *
  * Returns 1 if the session's state changes, otherwise 0.
  */
@@ -3855,12 +3863,25 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
        struct uri_auth *uri_auth = backend->uri_auth;
        struct user_auth *user;
        int authenticated, cur_idx;
-       char *h;
+       char *h, *e;
+
+       /* FIXME: this will soon be easier */
+       /* skip the method */
+       h = t->hreq.start.str;
+       e = h + t->hreq.start.len - uri_auth->uri_len;
+
+       while (h < e && *h != ' ' && *h != '\t')
+               h++;
+
+       /* find the URI */
+       while (h < e && (*h == ' ' || *h == '\t'))
+               h++;
 
-       if (t->hreq.start.len < uri_auth->uri_len + 4)   /* +4 for "GET " */
+       if (h >= e)
                return 0;
 
-       if (memcmp(t->hreq.start.str + 4, uri_auth->uri_prefix, uri_auth->uri_len) != 0)
+       /* the URI is in h */
+       if (memcmp(h, uri_auth->uri_prefix, uri_auth->uri_len) != 0)
                return 0;
 
        /* we are in front of a interceptable URI. Let's check