Repository: falconry/falcon

Issue:
Default OPTIONS responder does not set Content-Length to "0"
Per RFC 7231:

> A server MUST generate a Content-Length field with a value of "0" if no payload body is to be sent in the response.


Discussion:
codecov-io: ## [Current coverage](https://codecov.io/gh/falconry/falcon/pull/993?src=pr) is 100% (diff: 100%)
> Merging [#993](https://codecov.io/gh/falconry/falcon/pull/993?src=pr) into [master](https://codecov.io/gh/falconry/falcon/branch/master?src=pr) will not change coverage

```diff
@@           master   #993   diff @@
====================================
  Files          31     31          
  Lines        2066   2066          
  Methods         0      0          
  Messages        0      0          
  Branches      335    335          
====================================
  Hits         2066   2066          
  Misses          0      0          
  Partials        0      0          
```

> Powered by [Codecov](https://codecov.io?src=pr). Last update [673bb2e...4fa2fa6](https://codecov.io/gh/falconry/falcon/compare/673bb2e13613f04462a5515ba41f84dbab142970...4fa2fa63786fecc043c0dc370aa504756016240d?src=pr)

Patch:
diff --git a/falcon/responders.py b/falcon/responders.py
index da093e4..f4dce2f 100644
--- a/falcon/responders.py
+++ b/falcon/responders.py
@@ -17,7 +17,7 @@
 from falcon.errors import HTTPBadRequest
 from falcon.errors import HTTPMethodNotAllowed
 from falcon.errors import HTTPNotFound
-from falcon.status_codes import HTTP_204
+from falcon.status_codes import HTTP_200
 
 
 def path_not_found(req, resp, **kwargs):
@@ -56,7 +56,7 @@ def create_default_options(allowed_methods):
     allowed = ', '.join(allowed_methods)
 
     def on_options(req, resp, **kwargs):
-        resp.status = HTTP_204
+        resp.status = HTTP_200
         resp.set_header('Allow', allowed)
         resp.set_header('Content-Length', '0')
 


Test patch:
diff --git a/tests/test_after_hooks.py b/tests/test_after_hooks.py
index d3ca908..7847b85 100644
--- a/tests/test_after_hooks.py
+++ b/tests/test_after_hooks.py
@@ -210,7 +210,7 @@ class TestHooks(testing.TestCase):
 
         # Decorator should not affect the default on_options responder
         result = self.simulate_options('/wrapped')
-        self.assertEqual(result.status_code, 204)
+        self.assertEqual(result.status_code, 200)
         self.assertFalse(result.text)
 
     def test_wrapped_resource_with_hooks_aware_of_resource(self):
@@ -230,5 +230,5 @@ class TestHooks(testing.TestCase):
 
         # Decorator should not affect the default on_options responder
         result = self.simulate_options('/wrapped_aware')
-        self.assertEqual(result.status_code, 204)
+        self.assertEqual(result.status_code, 200)
         self.assertFalse(result.text)
diff --git a/tests/test_http_method_routing.py b/tests/test_http_method_routing.py
index 1f1e79b..7949692 100644
--- a/tests/test_http_method_routing.py
+++ b/tests/test_http_method_routing.py
@@ -89,6 +89,7 @@ class MiscResource(object):
         pass
 
     def on_options(self, req, resp):
+        # NOTE(kgriffs): The default responder returns 200
         resp.status = falcon.HTTP_204
 
         # NOTE(kgriffs): This is incorrect, but only return GET so
@@ -192,16 +193,16 @@ class TestHttpMethodRouting(testing.TestBase):
 
             self.assertThat(headers, Contains(allow_header))
 
-    def test_on_options(self):
+    def test_default_on_options(self):
         self.simulate_request('/things/84/stuff/65', method='OPTIONS')
-        self.assertEqual(self.srmock.status, falcon.HTTP_204)
+        self.assertEqual(self.srmock.status, falcon.HTTP_200)
 
         headers = self.srmock.headers
         allow_header = ('allow', 'GET, HEAD, PUT')
 
         self.assertThat(headers, Contains(allow_header))
 
-    def test_default_on_options(self):
+    def test_on_options(self):
         self.simulate_request('/misc', method='OPTIONS')
         self.assertEqual(self.srmock.status, falcon.HTTP_204)