OPTIONS always returns 200 - webserver

I am testing out cors on a website and an options request always returns 200 even if the requesting origin isn't authorized. If the origin isn't authorized they just do not add the headers. Does this fit the spec? It seems strange to me.

Yes, this is expected and acceptable per the spec. A non-200 response can and should be returned when a network or server error occurs. In the absence of a server or network error, the response headers should indicate which origins and methods are allowed. If your origin, for example, isn't among those present in the ACAO header in the response, then the user agent will abort and not send the original request.

Related

CORS response for request with unsupported methods

I am wondering how server should respond for CORS request that asks for unsupported method.
I have server endpoint, lets say server.com/endpoint which supports only GET. But client is sending CORS OPTIONS request with headers:
Origin: another.com
Access-Control-Request-Method: POST
How proper response should look? Should it return some error message about unsupported POST method, or just return 200 OK with typical CORS response headers like:
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: another.com
Or maybe I should treat it as request without CORS headers?
Also what should be returned in case of some random origin in request? Should i reveal which origins are allowed or keep it hidden and return no "Allow" headers?
I am wondering how server should respond for CORS request that asks for unsupported method.
I have server endpoint, lets say server.com/endpoint which supports only GET. But client is sending CORS OPTIONS request with headers:
Origin: another.com
Access-Control-Request-Method: POST
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests explains what’s happening: That OPTIONS is an expected request that browsers on their own automatically send as part of the CORS protocol.
How proper response should look? Should it return some error message about unsupported POST method
No, supporting the CORS protocol as expected on your server side doesn’t require you to send any special error response for this case. The browser just interprets the lack of "Allow" headers in the normal response as meaning that the server doesn’t allow the type of request it’s received.
or just return 200 OK with typical CORS response headers like:
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: another.com
That would be the right way to respond to it as far as supporting CORS as expected for the case where you get a request from the allowed origin another.com but for an unsupported method (e.g., POST, if you don’t support that). That enables the browser to log a specific CORS error on the client side to let the developer know the non-allowed method is the problem, not the origin.
Also what should be returned in case of some random origin in request? Should I reveal which origins are allowed or keep it hidden and return no "Allow" headers?
You can just return no "Allow" headers in the case of a non-allowed origin. There’s never any need to reveal what origins are allowed, except to allowed origins. (Anyway, the Access-Control-Allow-Origin value is always just going to contain either a single origin, or else the * wildcard, so no random origin making a request is going to be able to sniff out all the allowed origins.)
And to be clear, the CORS protocol in no way requires servers to respond to random non-allowed origins with any CORS headers at all. The semantics of the protocol are such that to a browser, a response with no "Allow" headers at all means, “This server does not allow cross-origin requests from your origin”. A random non-allowed origin doesn’t need any more information than just that.

RESTful status code for a request that cannot be satisfied because of a dependency issue

My payment endpoint which accepts a POST should deny requests when the user does not have any payment methods configured. What is the correct HTTP status code in this case?
What is the correct HTTP status code to be raised when the system itself cannot reach the state asked for by the request and another request (creating a payment method) must be completed first?
I looked at 428 Precondition Required, but that seems to have more to do with the headers than the state of the system.
I would go simply with 400 Bad Request. If you need more specific instructions or hints in the response, you can return a body, which will indicate the exact nature of the error.
You don't need to assign a specific HTTP error code to all your internal business-related error cases. Indeed this is probably not possible anyway.
The specification on 400: https://www.rfc-editor.org/rfc/rfc7231#section-6.5.1
Relevant quotes from there:
indicates that the server cannot or will not process the request due to something that is perceived to be a client error
And about the 4xx codes in general:
the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition
Did you look into error 424 Failed_Dependency? I think this could bethe one you want.
See
http://www.restpatterns.org/HTTP_Status_Codes/424_-_Failed_Dependency

Rest endpoint with success and a helpful warning

I have a request from the client - when the user performs an action, there can be 3 actions:
the action succeeds with 200 OK status
the action fails (400) with an error message
the action succeeds but we need to display a helpful warning message to the user. This happens when the allocated amount is almost used up.
There does not seem to be a way for REST APIs to return an indication that the action completed successfully with some helpful information that further action might fail.
Thanks
HTTP response codes are limited and I think, those to be used to indicate any generic response. To have application specific response codes or response strings, it is better to have application level response codes to be communicated via HTTP response payload.
You didn't mention which HTTP method you are preparing for. Using GET should of course not modify anything, so I'm assuming it's either POST or PUT.
For POST, the response should be 201 Created. There should be a Location header line indicating the resource that was created.
For PUT, the response should be 200 OK.
In both cases, you can return a content body, as others suggested. This body can be some status information about the current state of whatever resource you are using. Note, that this status information might be reachable explicitly by some other URI, so it can share a mime-type with that "status" resource.
REST is using HTTP methods and HTTP status to represent the status of reply, by checking HTTP status I can find code 203 I think it could be suitable for your 3rd case :
203 Non-Authoritative Information (since HTTP/1.1)
The server successfully processed the request, but is returning information that may be from another source.

What is the correct way to return a specialized HTTP response?

Let's say that in my RESTful interface I require the client to include some special header, just to indicate it's an authorized client. (Trust me on this; it's a requirement of the project.) If the HTTP request contains an incorrect value in this header, the server needs to send back an HTTP response that the client can recognize that it sent an unsupported value in the header.
What's the appropriate way to send back this information using HTTP?
I could send back a 400 Bad Request response, but how do I tell the client what the problem was exactly? The obvious option is to include some message in the body of the response. But (besides issues of i18n) is it really a good idea for the client to blindly display the contents of an error message?
I could send back a 400 Bad Request response, with a proprietary special header indicating that such-and-such header had the wrong code. This has the benefit that the client can actually process what the error was (as opposed to free text in the content). So does the 400 response then become a catch-all response, with the actual error in some proprietary header? Is this a good general pattern? But that almost suggests...
I could could send back some arbitrary 4XX response that has a proprietary meaning, such as 472 Bad Foo Header Value. Microsoft seems to have gone this route at times. The obvious problem is the possibility of clashes in a future version of HTTP (or with others who have done the same thing).
I suppose I'm leaning more toward 400 Bad Request with a special header indicating the error specialization. Any thoughts or experience with this use case?
If the special header is incorrectly formatted then you could send a
400 Bad request Response indicating that the header is wrong.
However If the sole purpose of the header is authorization and you reject the header, because of invalid value, then I would opt for:
403 - Forbidden, if you want the connection to be refused
401 - Unauthorized, if the client should try to reauthenticate
In the Response phrase you can indicate the reason for refusing the connection.

url shortener 301 redirection understanding

We're working on a URL shortener project in PHP. We're using 301 HTTP redirection and naturally track our links visits. but there is something strange :
After we shorten a URL and go through it by a browser, only the first visit is tracked, and it seems that no other request is sent to our server and it directly goes to the destination URL.(I think this is a browser cache after one try). But :
When trying with a similar service like bitly , it has different treat. some of the same requests on the same browsers are tracked in bitly visit tracking (In fact more than one of them, and I don't understand why, I don't see any logic) while they also use 301 redirection.(at left bottom of browser window sometimes writes "waiting for bit.ly..." and sometimes not , in fact randomly).
Are any tricks included here? What this different treat happens?
Read the HTTP specification. A 301 response tells the browser that the requested resource has permanantly moved to the new URL that is being redirected to, and should not use the original URL anymore:
10.3.2 301 Moved Permanently
The requested resource has been assigned a new permanent URI and
any future references to this resource SHOULD use one of the
returned URIs. Clients with link editing capabilities ought to
automatically re-link references to the Request-URI to one or more
of the new references returned by the server, where possible. This
response is cacheable unless indicated otherwise.
The new permanent URI SHOULD be given by the Location field in the
response. Unless the request method was HEAD, the entity of the
response SHOULD contain a short hypertext note with a hyperlink to
the new URI(s).
If the 301 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.
Note: When automatically redirecting a POST request after
receiving a 301 status code, some existing HTTP/1.0 user agents
will erroneously change it into a GET request.
For what you are attempting, try using 302, 303, or 307 instead.
10.3.3 302 Found
The requested resource resides temporarily under a different URI.
Since the redirection might be altered on occasion, the client SHOULD
continue to use the Request-URI for future requests. This response
is only cacheable if indicated by a Cache-Control or Expires header
field.
The temporary URI SHOULD be given by the Location field in the
response. Unless the request method was HEAD, the entity of the
response SHOULD contain a short hypertext note with a hyperlink to
the new URI(s).
If the 302 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.
Note: RFC 1945 and RFC 2068 specify that the client is not allowed
to change the method on the redirected request. However, most
existing user agent implementations treat 302 as if it were a 303
response, performing a GET on the Location field-value regardless
of the original request method. The status codes 303 and 307 have
been added for servers that wish to make unambiguously clear which
kind of reaction is expected of the client.
.
10.3.4 303 See Other
The response to the request can be found under a different URI and
SHOULD be retrieved using a GET method on that resource. This method
exists primarily to allow the output of a POST-activated script to
redirect the user agent to a selected resource. The new URI is not a
substitute reference for the originally requested resource. The 303
response MUST NOT be cached, but the response to the second
(redirected) request might be cacheable.
The different URI SHOULD be given by the Location field in the
response. Unless the request method was HEAD, the entity of the
response SHOULD contain a short hypertext note with a hyperlink to
the new URI(s).
Note: Many pre-HTTP/1.1 user agents do not understand the 303
status. When interoperability with such clients is a concern, the
302 status code may be used instead, since most user agents react
to a 302 response as described here for 303.
.
10.3.8 307 Temporary Redirect
The requested resource resides temporarily under a different URI.
Since the redirection MAY be altered on occasion, the client SHOULD
continue to use the Request-URI for future requests. This response
is only cacheable if indicated by a Cache-Control or Expires header
field.
The temporary URI SHOULD be given by the Location field in the
response. Unless the request method was HEAD, the entity of the
response SHOULD contain a short hypertext note with a hyperlink to
the new URI(s) , since many pre-HTTP/1.1 user agents do not
understand the 307 status. Therefore, the note SHOULD contain the
information necessary for a user to repeat the original request on
the new URI.
If the 307 status code is received in response to a request other
than GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.
Just to note down my comments..
Cache control headers also plays a role on this. If you check with curl or firebug persistant tracking, you can see the cache control headers before the location. bitly is configured to be contacted back if user clicks on the links after 90 seconds.