0

Example:

  • We provide a URL http://.../foo/download.csv
  • web client (MS office) opens above URL and tries to access (for reasons I really don't know) http://.../foo/ with an http OPTIONS request.
  • Up to now or app returns 404 since the above URL does not exist (even for GET requests).

I think All OPTIONS requests should get a 405. It should not matter if the URL would be accessible via GET or POST.

Does this match the http spec?

Here is my explanation why I think 405 fits better: If there is an OPTIONS request, I don't want to look at the path. I don't care what the path looks like, there should always be the same answer: Not allowed.

Up to now it depends: if there is a GET-view registered, then we return 405. Otherwise a 404 gets returned.

Update: 404 vs 405

HTTP-Spec 405 Method Not Allowed

The method specified in the Request-Line is not allowed for the resource identified by the Request-URI. The response MUST include an Allow header containing a list of valid methods for the requested resource.

Source: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6

guettli
  • 25,042
  • 81
  • 346
  • 663
  • Can you provide your `views.py` and `urls.py`, or at least the relevant parts of it? – Назар Топольський Dec 05 '16 at 13:01
  • 1
    I don't think your argument to why 405 fits better is correct. The `Method not allowed` means that you're accesing an existing resource using an unallowed action, while `Not found` means that the resource doesn't exist or can't be found, not matter how you pretend to use it. Also it would be incosistent to have an unexisting resource that is not allowed to be used with `OPTIONS`, why it isn't allowed with `OPTIONS` if it can't be found or it doesn't exist? How do you know it's unallowed if you couldn't found it? – Mr. E Dec 05 '16 at 15:35
  • I'd agree with Mr E. here - it makes sense for it to 404 first. The methods that are allowed are secondary to *whether or not a resource exists at that location*. You asked what the Django/Pythonic way would be, and I believe my answer gives the least-unacceptable version of that. Ultimately, you're still overriding what is some very common and well-understood behaviour: if a resource does not exist, return a 404. – Withnail Dec 05 '16 at 21:00
  • @Withnail I updated the question. The question is no more about django/python. It is about the http spec. I am still unsure. Maybe you are right, but on the other hand I still like the simple "if OPTIONS, then return 405" – guettli Dec 06 '16 at 11:03
  • Well, that makes it a pretty different question from the one you originally asked. From the W3 spec you've quoted, the answer I've given is still the valid one. You can't specify the methods that are allowed on a resource that doesn't exist at a given URI. – Withnail Dec 06 '16 at 11:14
  • @Withnail I can't specify the methods that are allowed on a resource that doesn't exist at a given URI? I guess it is possible: An empty list. But you are right. This makes me think you are right: first check http-path, then check http-method. – guettli Dec 06 '16 at 12:01

1 Answers1

1

It's not really clear why you want it to return a 405, to be honest. It'll never get as far as checking the method, because the 404 handler will be invoked first - there's no view logic for it to get, that's what the 404 is. This is the default, and correct, behaviour.

I suspect, if you don't want to write custom middleware for it, and you insist on implementing it, that overriding the 404 handler would be the way forward - if a 404 Handler is invoked, check the method and return that accordingly - this is messy though, and the custom middleware would be more pythonic.

def handler404(request): 
    if request.method == 'OPTION': 
        #return your custom 405 response
    else: 
        #go on and do your regular 404. 
Withnail
  • 3,128
  • 2
  • 30
  • 47