Skip to content
This repository
Browse code

Ensuring that HTTP methods accept request bodies in accordance with v…

…arious RFCs (RFC2518, RFC2616, RFC3253, RFC5789). Included QA test for all methods.
  • Loading branch information...
commit e6d7fa953822f7f7747c3a1324301f17dba7219a 1 parent e8255e2
David Beitey authored August 30, 2012
2  cherokee/handler_cgi.c
@@ -367,7 +367,7 @@ add_environment (cherokee_handler_cgi_t *cgi,
367 367
 
368 368
 	/* CONTENT_LENGTH
369 369
 	 */
370  
-	if (http_method_with_input (conn->header.method)) {
  370
+	if (conn->post.has_info) {
371 371
 		cherokee_buffer_clean (tmp);
372 372
 		cherokee_buffer_add_ullong10 (tmp, conn->post.len);
373 373
 		set_env (cgi_base, "CONTENT_LENGTH", tmp->buf, tmp->len);
4  cherokee/handler_fcgi.c
@@ -404,7 +404,7 @@ add_extra_fcgi_env (cherokee_handler_fcgi_t *hdl, cuint_t *last_header_offset)
404 404
 
405 405
 	/* POST management
406 406
 	 */
407  
-	if (http_method_with_input (conn->header.method)) {
  407
+	if (conn->post.has_info) {
408 408
 		if (conn->post.encoding == post_enc_regular) {
409 409
 			cherokee_buffer_add_ullong10 (&buffer, conn->post.len);
410 410
 			set_env (cgi_base, "CONTENT_LENGTH", buffer.buf, buffer.len);
@@ -516,7 +516,7 @@ build_header (cherokee_handler_fcgi_t *hdl, cherokee_buffer_t *buffer)
516 516
 
517 517
 	/* No POST?
518 518
 	 */
519  
-	if ((! http_method_with_input (conn->header.method)) || (! conn->post.has_info) || (! conn->post.len)) {
  519
+	if ((! conn->post.has_info) || (! conn->post.len)) {
520 520
 		TRACE (ENTRIES",post", "Post: %s\n", "has no post");
521 521
 		add_empty_packet (hdl, FCGI_STDIN);
522 522
 	}
22  cherokee/http.h
@@ -224,18 +224,32 @@ typedef enum {                               /* Protocol   RFC  Section */
224 224
 
225 225
 #define http_method_with_body(m)  ((m) != http_head)
226 226
 
  227
+/* RFC 2518, RFC 2616, RFC3253, RFC 5789 */
227 228
 #define http_method_with_input(m) ((m == http_post)      || \
228 229
 				   (m == http_put)       || \
229  
-				   (m == http_mkcol)     || \
230 230
 				   (m == http_merge)     || \
231 231
 				   (m == http_search)    || \
232 232
 				   (m == http_report)    || \
233  
-				   (m == http_checkout)  || \
  233
+				   (m == http_patch)     || \
234 234
 				   (m == http_propfind)  || \
235 235
 				   (m == http_proppatch) || \
236  
-				   (m == http_mkactivity))
  236
+				   (m == http_update)    || \
  237
+				   (m == http_label))
237 238
 
238  
-#define http_method_with_optional_input(m) (m == http_options)
  239
+#define http_method_with_optional_input(m) ((m == http_options)		  || \
  240
+					    (m == http_delete)		  || \
  241
+					    (m == http_mkcol)		  || \
  242
+					    (m == http_copy)		  || \
  243
+					    (m == http_move)		  || \
  244
+					    (m == http_lock)		  || \
  245
+					    (m == http_unlock)		  || \
  246
+					    (m == http_version_control)	  || \
  247
+					    (m == http_checkout)	  || \
  248
+					    (m == http_uncheckout)	  || \
  249
+					    (m == http_checkin)		  || \
  250
+					    (m == http_mkworkspace)	  || \
  251
+					    (m == http_mkactivity)	  || \
  252
+					    (m == http_baseline_control))
239 253
 
240 254
 
241 255
 /* RFC 2616: Section 4.3 */
117  qa/299-MethodsRequestBodyHandling.py
... ...
@@ -0,0 +1,117 @@
  1
+from base import *
  2
+
  3
+DIR = "299-MethodsRequestBodyHandling"
  4
+MAGIC = "Report bugs to http://bugs.cherokee-project.com"
  5
+
  6
+METHODS = {
  7
+    'required': [
  8
+        'POST',
  9
+        'PUT',
  10
+        'MERGE',
  11
+        'SEARCH',
  12
+        'REPORT',
  13
+        'PATCH',
  14
+        'PROPFIND',
  15
+        'PROPPATCH',
  16
+        'UPDATE',
  17
+        'LABEL',
  18
+    ],
  19
+    'optional': [
  20
+        'OPTIONS',
  21
+        'DELETE',
  22
+        'MKCOL',
  23
+        'COPY',
  24
+        'MOVE',
  25
+        'LOCK',
  26
+        'UNLOCK',
  27
+        'VERSION-CONTROL',
  28
+        'CHECKOUT',
  29
+        'UNCHECKOUT',
  30
+        'CHECKIN',
  31
+        'MKWORKSPACE',
  32
+        'MKACTIVITY',
  33
+        'BASELINE-CONTROL',
  34
+    ]
  35
+}
  36
+
  37
+CONF = """
  38
+vserver!1!rule!1280!match = directory
  39
+vserver!1!rule!1280!match!directory = /%s
  40
+vserver!1!rule!1280!handler = common
  41
+""" % (DIR)
  42
+
  43
+
  44
+class TestEntry (TestBase):
  45
+    """Test for HTTP methods with required and optional request bodies being
  46
+    received and processed correctly by Cherokee.
  47
+    """
  48
+
  49
+    def __init__ (self, method, send_input, input_required):
  50
+        TestBase.__init__ (self, __file__)
  51
+        self.request = "%s /%s/ HTTP/1.0\r\n" % (method, DIR) +\
  52
+                       "Content-type: text/xml\r\n"
  53
+        self.expected_content = []
  54
+        
  55
+        if input_required and not send_input:
  56
+            self.expected_error = 411
  57
+        else:
  58
+            self.expected_error = 200
  59
+            self.expected_content.append("Method: %s" % method)
  60
+
  61
+        if send_input:
  62
+            self.request += "Content-length: %d\r\n" % (len(MAGIC))
  63
+            self.post = MAGIC
  64
+            self.expected_content.append("Body: %s" % MAGIC)
  65
+        else:
  66
+            self.forbidden_content = 'Body:'
  67
+
  68
+
  69
+class Test (TestCollection):
  70
+
  71
+    def __init__ (self):
  72
+        TestCollection.__init__ (self, __file__)
  73
+
  74
+        self.name = "Method Request Body Handling"
  75
+        self.conf = CONF
  76
+        self.proxy_suitable = True
  77
+
  78
+    def Prepare (self, www):
  79
+        d = self.Mkdir (www, DIR)
  80
+        f = self.WriteFile (d, "test_index.php", 0444,
  81
+                            """
  82
+<?php echo 'Method: '.$_SERVER['REQUEST_METHOD']; ?>
  83
+
  84
+<?php
  85
+    $body = @file_get_contents('php://input');
  86
+    if (strlen($body) > 0):
  87
+        echo "Body: $body";
  88
+    endif;
  89
+?>
  90
+                            """)
  91
+
  92
+    def JustBefore (self, www):
  93
+        # Create sub-request objects
  94
+        self.Empty ()
  95
+
  96
+        # Create all tests with different methods - all methods
  97
+        # should only work with request bodies. With no request
  98
+        # body a 411 Length Required should result.
  99
+        for method in METHODS['required']:
  100
+            self.Add (TestEntry (method=method,
  101
+                                 send_input=True,
  102
+                                 input_required=True))
  103
+            self.Add (TestEntry (method=method,
  104
+                                 send_input=False,
  105
+                                 input_required=True))
  106
+
  107
+        # Create all tests with different methods - all methods
  108
+        # should work with and without request bodies.
  109
+        for method in METHODS['optional']:
  110
+            #Test method when for when sending a request body
  111
+            self.Add (TestEntry (method=method,
  112
+                                 send_input=True,
  113
+                                 input_required=False))
  114
+            #Test method when not sending a request body
  115
+            self.Add (TestEntry (method=method,
  116
+                                 send_input=False,
  117
+                                 input_required=False))

0 notes on commit e6d7fa9

Please sign in to comment.
Something went wrong with that request. Please try again.