Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@davidjb davidjb authored
View
2  cherokee/handler_cgi.c
@@ -367,7 +367,7 @@ add_environment (cherokee_handler_cgi_t *cgi,
/* CONTENT_LENGTH
*/
- if (http_method_with_input (conn->header.method)) {
+ if (conn->post.has_info) {
cherokee_buffer_clean (tmp);
cherokee_buffer_add_ullong10 (tmp, conn->post.len);
set_env (cgi_base, "CONTENT_LENGTH", tmp->buf, tmp->len);
View
4 cherokee/handler_fcgi.c
@@ -404,7 +404,7 @@ add_extra_fcgi_env (cherokee_handler_fcgi_t *hdl, cuint_t *last_header_offset)
/* POST management
*/
- if (http_method_with_input (conn->header.method)) {
+ if (conn->post.has_info) {
if (conn->post.encoding == post_enc_regular) {
cherokee_buffer_add_ullong10 (&buffer, conn->post.len);
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)
/* No POST?
*/
- if ((! http_method_with_input (conn->header.method)) || (! conn->post.has_info) || (! conn->post.len)) {
+ if ((! conn->post.has_info) || (! conn->post.len)) {
TRACE (ENTRIES",post", "Post: %s\n", "has no post");
add_empty_packet (hdl, FCGI_STDIN);
}
View
22 cherokee/http.h
@@ -224,18 +224,32 @@ typedef enum { /* Protocol RFC Section */
#define http_method_with_body(m) ((m) != http_head)
+/* RFC 2518, RFC 2616, RFC3253, RFC 5789 */
#define http_method_with_input(m) ((m == http_post) || \
(m == http_put) || \
- (m == http_mkcol) || \
(m == http_merge) || \
(m == http_search) || \
(m == http_report) || \
- (m == http_checkout) || \
+ (m == http_patch) || \
(m == http_propfind) || \
(m == http_proppatch) || \
- (m == http_mkactivity))
+ (m == http_update) || \
+ (m == http_label))
-#define http_method_with_optional_input(m) (m == http_options)
+#define http_method_with_optional_input(m) ((m == http_options) || \
+ (m == http_delete) || \
+ (m == http_mkcol) || \
+ (m == http_copy) || \
+ (m == http_move) || \
+ (m == http_lock) || \
+ (m == http_unlock) || \
+ (m == http_version_control) || \
+ (m == http_checkout) || \
+ (m == http_uncheckout) || \
+ (m == http_checkin) || \
+ (m == http_mkworkspace) || \
+ (m == http_mkactivity) || \
+ (m == http_baseline_control))
/* RFC 2616: Section 4.3 */
View
117 qa/299-MethodsRequestBodyHandling.py
@@ -0,0 +1,117 @@
+from base import *
+
+DIR = "299-MethodsRequestBodyHandling"
+MAGIC = "Report bugs to http://bugs.cherokee-project.com"
+
+METHODS = {
+ 'required': [
+ 'POST',
+ 'PUT',
+ 'MERGE',
+ 'SEARCH',
+ 'REPORT',
+ 'PATCH',
+ 'PROPFIND',
+ 'PROPPATCH',
+ 'UPDATE',
+ 'LABEL',
+ ],
+ 'optional': [
+ 'OPTIONS',
+ 'DELETE',
+ 'MKCOL',
+ 'COPY',
+ 'MOVE',
+ 'LOCK',
+ 'UNLOCK',
+ 'VERSION-CONTROL',
+ 'CHECKOUT',
+ 'UNCHECKOUT',
+ 'CHECKIN',
+ 'MKWORKSPACE',
+ 'MKACTIVITY',
+ 'BASELINE-CONTROL',
+ ]
+}
+
+CONF = """
+vserver!1!rule!1280!match = directory
+vserver!1!rule!1280!match!directory = /%s
+vserver!1!rule!1280!handler = common
+""" % (DIR)
+
+
+class TestEntry (TestBase):
+ """Test for HTTP methods with required and optional request bodies being
+ received and processed correctly by Cherokee.
+ """
+
+ def __init__ (self, method, send_input, input_required):
+ TestBase.__init__ (self, __file__)
+ self.request = "%s /%s/ HTTP/1.0\r\n" % (method, DIR) +\
+ "Content-type: text/xml\r\n"
+ self.expected_content = []
+
+ if input_required and not send_input:
+ self.expected_error = 411
+ else:
+ self.expected_error = 200
+ self.expected_content.append("Method: %s" % method)
+
+ if send_input:
+ self.request += "Content-length: %d\r\n" % (len(MAGIC))
+ self.post = MAGIC
+ self.expected_content.append("Body: %s" % MAGIC)
+ else:
+ self.forbidden_content = 'Body:'
+
+
+class Test (TestCollection):
+
+ def __init__ (self):
+ TestCollection.__init__ (self, __file__)
+
+ self.name = "Method Request Body Handling"
+ self.conf = CONF
+ self.proxy_suitable = True
+
+ def Prepare (self, www):
+ d = self.Mkdir (www, DIR)
+ f = self.WriteFile (d, "test_index.php", 0444,
+ """
+<?php echo 'Method: '.$_SERVER['REQUEST_METHOD']; ?>
+
+<?php
+ $body = @file_get_contents('php://input');
+ if (strlen($body) > 0):
+ echo "Body: $body";
+ endif;
+?>
+ """)
+
+ def JustBefore (self, www):
+ # Create sub-request objects
+ self.Empty ()
+
+ # Create all tests with different methods - all methods
+ # should only work with request bodies. With no request
+ # body a 411 Length Required should result.
+ for method in METHODS['required']:
+ self.Add (TestEntry (method=method,
+ send_input=True,
+ input_required=True))
+ self.Add (TestEntry (method=method,
+ send_input=False,
+ input_required=True))
+
+ # Create all tests with different methods - all methods
+ # should work with and without request bodies.
+ for method in METHODS['optional']:
+ #Test method when for when sending a request body
+ self.Add (TestEntry (method=method,
+ send_input=True,
+ input_required=False))
+ #Test method when not sending a request body
+ self.Add (TestEntry (method=method,
+ send_input=False,
+ input_required=False))
Please sign in to comment.
Something went wrong with that request. Please try again.