marshmallow-code / apispec-webframeworks

Web framework plugins for apispec (formally in apispec.ext).
MIT License
31 stars 22 forks source link

RFC: enforce method order for one endpoint in the spec #15

Open lafrech opened 5 years ago

lafrech commented 5 years ago

Issue by lafrech Wednesday Apr 04, 2018 at 13:39 GMT Originally opened as https://github.com/marshmallow-code/apispec/issues/193


Although json objects are not ordered, some tools respect the order in the OpanAPI json file to display the spec. Therefore, it makes sense to respect the order desired by the user when writing the spec file. Several PRs are based on this assumption (#86, #87, #189).

It could be nice to enforce the order of the methods for each endpoint. For instance, always present the methods in this order:

HTTP_METHODS = ['OPTIONS', 'HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'TRACE']

The order list being a module variable, it could be mutated by the user if another order is required.

This feature requires modifications in flask, tornado, and perhaps bottle extensions. More details in https://github.com/marshmallow-code/apispec/pull/189.

Edit: I'd remove 'TRACE' from the list as it is not in VALID_METHODS.

Edit again: OpenAPI 3 contains TRACE (https://github.com/marshmallow-code/apispec/issues/165#issuecomment-388753808).

lafrech commented 5 years ago

Comment by lafrech Thursday Apr 05, 2018 at 09:55 GMT


Note that this makes sense if the spec file is served without breaking the order.

When using flask, jsonify breaks the order, unless app.config["JSON_SORT_KEYS"] == False (https://github.com/pallets/flask/issues/974).

I suspect flask-apispec doesn't get the right order, then, as it uses jsonify (https://github.com/jmcarp/flask-apispec/blob/master/flask_apispec/extension.py#L88).

To serve the docs with Flask without breaking the order and without unsetting JSON_SORT_KEYS, one may to call json.dump directly, like I did in flask-rest-api:

    def _openapi_json(self):
        """Serve JSON spec file"""
        # We don't use Flask.jsonify here as it would sort the keys
        # alphabetically while we want to preserve the order.
        return current_app.response_class(
            json.dumps(self.to_dict(), indent=2),
            mimetype='application/json')