inveniosoftware / flask-resources

REST APIs for Flask
https://flask-resources.readthedocs.io
MIT License
3 stars 21 forks source link

errors: orders are not properly addressed #36

Closed ppanero closed 4 years ago

ppanero commented 4 years ago

If an HTTP verb corresponding method (read, create....) is not defined, accessing the endpoint should return 405. It doesn't do that for update for instance, because load_request is attempted first which may result in 400 even if the method is not defined at all. try-except must be done twice and checked to solve this. We can't rely on pre-running the method because it may have side-effects. Errors should therefore be revisited:

fenekku commented 4 years ago

Case ii, 405 if route but no method is quite problematic.

Flask is in charge of routing at the route and method level. It means that once control flow gets to one of our methods, by definition, that method exists i.e. not a real 405. We try to fake the 405 by returning it by default, but that default is only returned after content-negotiation. This means that content-negotiation errors are raised first. That doesn't make sense in practice from a user's perspective: negotiating content for a non existent endpoint?!

We obviously can't reverse the order because we don't know before we hit the business logic (create/read/...) if the method returns a faked 405.

And we always get to one of our methods, because we create MethodView classes with get/post/... implemented.

There are 2 potential solutions I am considering after much thought: (please share if you have others!)

  1. We stop using MethodView classes with all endpoints defined and only build the endpoints for the defined search/read/... methods. This is only possible by bringing in Python Metaclasses. We can follow: https://github.com/pallets/flask/blob/024f0d384cf5bb65c76ac59f8ddce464b2dc2ca1/src/flask/views.py#L100 but it requires some careful thought. Also it affects decorators and so on...

  2. We just say that all endpoints are implemented by default and return 200.

It is sad that it took me the whole day to get to 2. :sob: .

Given our context, option 2. is the easiest to do. Option 1. would be more "correct" and play nicer with other endpoints. A potential todo. What do you think?