Repository: marshmallow-code/flask-smorest

Issue:
304 wrongly documented as following ErrorSchema
Automatic doc says 304 comes with a JSON payload. This is not true.

From https://httpstatuses.com/304:

> A 304 response cannot contain a message-body; it is always terminated by the first empty line after the header fields.

Flask/werkzeug respect that and 304 responses have an empty body.

Autodoc should be fixed.

We should clarify first which codes are concerned. There could be more than just 304 concerned.

Also, when `NotModified` is raised, we go through the error handler. This is useless since the payload is trashed. I don't think we should worry about that.

Discussion:

Patch:
diff --git a/flask_smorest/spec/__init__.py b/flask_smorest/spec/__init__.py
index d78332d..7116b8e 100644
--- a/flask_smorest/spec/__init__.py
+++ b/flask_smorest/spec/__init__.py
@@ -307,8 +307,9 @@ class APISpecMixin(DocBlueprintMixin):
         for status in http.HTTPStatus:
             response = {
                 "description": status.phrase,
-                "schema": self.ERROR_SCHEMA,
             }
+            if not (100 <= status < 200) and status not in (204, 304):
+                response["schema"] = self.ERROR_SCHEMA
             prepare_response(response, self.spec, DEFAULT_RESPONSE_CONTENT_TYPE)
             self.spec.components.response(status.name, response, lazy=True)
 


Test patch:
diff --git a/tests/test_spec.py b/tests/test_spec.py
index cddc599..c691a85 100644
--- a/tests/test_spec.py
+++ b/tests/test_spec.py
@@ -60,20 +60,23 @@ class TestAPISpec:
 
         # Errors are now registered
         for status in http.HTTPStatus:
+            response = responses[status.name]
+            assert response["description"] == status.phrase
+            empty_body = (100 <= status < 200) or status in (204, 304)
             if openapi_version == "2.0":
-                assert responses[status.name] == {
-                    "description": status.phrase,
-                    "schema": build_ref(api.spec, "schema", "Error"),
-                }
+                if empty_body:
+                    assert "schema" not in response
+                else:
+                    assert response["schema"] == build_ref(api.spec, "schema", "Error")
             else:
-                assert responses[status.name] == {
-                    "description": status.phrase,
-                    "content": {
+                if empty_body:
+                    assert "content" not in response
+                else:
+                    assert response["content"] == {
                         "application/json": {
                             "schema": build_ref(api.spec, "schema", "Error")
                         }
-                    },
-                }
+                    }
 
     @pytest.mark.parametrize("openapi_version", ["2.0", "3.0.2"])
     def test_api_lazy_registers_etag_headers(self, app, openapi_version):