Several our REST service needs to indicate that further action needs to be taken by the client to fulfill the request (very often that the response to the request can be found under another URI).
In general this is achieved by means of HTTP 3xx responses. However, in case of JavaScript based client the redirection is performed by the browser itself before the response can reach JavaScript code.
Basically what I need is a RESTful way to inform the client (JavaScript code) that the response can be found under another URI and let the client process such a response on its own.
I am thinking about two solutions:
HTTP 200 OK with the entity containing URI to follow. I do not like creating a whole entity carrying only URI. I would rather to achieve this via HTTP headers
HTTP 204 No Content response with the Location header containing the given URI. But here I am not sure if it is "REST compliant". Is it OK to combine HTTP 204 No Content with Location header that is used mainly in redirection (along with HTTP 3xx responses), or when a new resource has been created?
Or is there a better solution?
If I understand you correctly, you have a process, say of 5 steps. After step 5 there is some result prepared, to which you want to point your client, not via HTTP-3xx, but in a cleaner way.
I would suggest, that you make use of the link property in your JSON-response:
{
...
"links": [
...
"result": { "href": "/calculation/1234" }
...
]
}
Your client could take this answer and transform it to a simple link/button.
This is conforming with HATEOAS (Hypermedia As The Engine Of Application State), indicating, that the current state offers the result under a different location which is referenced.
Assuming you have a json response format, you could accept a request parameter like noredirect that when present sets the http response code to 200 and set the real response code in the returned object.
GET /some/resource
200 OK
{
status: 200,
…
}
GET /some/unknown/resource
404 Not Found
{
status: 404,
…
}
GET /some/unknown/resource?noredirect
200 OK
{
status: 404,
…
}
Related
I'm looking to dynamically issue a new HTTP request from the client/browser based on response from an earlier HTTP request, in the same page load. Basically, the flow would look something like this:
Issue HTTP request to www.site1.com/fetch, and parse response to get some string mydata.
Issue HTTP request to www.site2.com/lookup?key={mydata}, substituting in the data just obtained. This call should be done in the same page load.
This is related to HTTP redirections, but it's done on the client-side with more flexibility, to possibly a different domain.
I think client-side JS is the best way to achieve this (perhaps with some kind of callback), but I'm open to other ideas.
I need to create REST API endpoint, and I am not sure which HTTP code to return as status.
Requirements are next:
- My API should accept URL as a parameter
- Make an API call to third-party service (use URL), and get a response
- Return response (content that fetched from third-party service)
In some cases, everything works fine. A call is made to external service, it returns content and status code 200.
But, sometimes there is no content and it returns 404. (Important, it is possible that content will be available in the future.)
From the perspective of my system, it is the regular situation.
Which HTTP code should I return?
202 - Accepted,
204 - No content,
206 - Partial content
or something else?
404 Not Found
The requested resource could not be found but may be available in the future. Subsequent requests by the client are permissible.
In REST-API request and response should only work with current "call". If the content is currently not available it should return 404 status. And It(404) is the exact status that should be returned.
However, if you want to bend the rules, 204 status code seems more appropriate. I'm not recommending you to do this.
204 No Content
The server successfully processed the request and is not returning any content Link.
Instead of creating the actual resources, create a temporary one. Instead of returning a 201 (Created) HTTP response, you can issue a 202 (Accepted) response code. This informs the client that the request has been accepted and understood by the server, but the resource is not (yet) created.
From: http://restcookbook.com/Resources/asynchroneous-operations/
You should return whatever the HTTP status code return by third party service unless your system is wrapping it up and processing it and changing the status.
I use the jQuery ajax functions to access a web service, but the server, instead of returning a response with a status code describing a problem, the request is redirected to a page with a 200 header, describing the problem. I can't make any changes to this, so I need to solve it on the client somehow.
Example:
A request goes to some URL which is not found, so I receive a 302 Redirect to another location. A new request is sent, and I receive a 200 OK, thus preventing the error callback to fire.
Is there some way I can prevent the ajax request to follow redirects and instead invoke a callback, preferably the error method. Alternatively, is it possible to detect if a redirect has happened in the client?
I find your question interesting, but the problem in whole seems me more a misunderstanding. At least I'll try to explain my understanding of the problem.
The silent (transparent) redirection is the part of XMLHttpRequest specification (see here especially the words "... transparently follow the redirect ..."). The standard mention only that the user agent (the web browser) can prevent or notify of certain kinds of automatic redirections, but it's not a part of XMLHttpRequest. It's the part of HTTP client configuration (OS configuration) or the web browser configuration. So jQuery.ajax can't have any option where you can prevent redirection.
You can see that HTTP redirection is the part of HTTP protocol and not a part of XMLHttpRequest. So it's on the another level of abstraction or the network stack. For example the data from the XMLHttpRequest can be retrieved from the HTTP proxy or from the local browser cache, and it's the part of HTTP protocol. Mostly the server which provide the data and not the client can influence on caching.
You can compare the requirement from your question with the requirement to prevent changing of IP address of the web server or the changing of the IP route during the communication. All the things can be interesting in some scenarios, but there are parts of another level of the communication stack and can't be managed by jQuery.ajax or XMLHttpRequest.
The XMLHttpRequest standard say that the client configuration can have options which prevent redirection. In case of "Microsoft world", which I better know, you can look at WinHttpSetOption function which can be used to set WINHTTP_OPTION_DISABLE_FEATURE option with the WINHTTP_DISABLE_REDIRECTS value. Another way are the usage of WINHTTP_OPTION_REDIRECT_POLICY option with the WINHTTP_OPTION_REDIRECT_POLICY_NEVER value. One more feature which one can use in Windows is the WinHttpSetStatusCallback function which can set callback function received some notifications like WINHTTP_CALLBACK_FLAG_REDIRECT.
So it's do possible to implement your requirements in general, but the solution will be probably not independent from the operation system or the web browser and be not on the level of jQuery.ajax or XMLHttpRequest.
I don't believe it is possible. The underlying library (XHR) makes the new request transparently. That being said, what I have done in these situations (usually a session-timeout type of deal that takes me to a login page) is send back a custom response header. I also have setup a global ajax handler that checks for the presence of that header, and responds appropriately when present (for example, redirecting the whole page to the login screen).
In case you're interested, here's the jQuery code I have to watch for that custom header:
/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
if (xhr.readyState == 4)
{
if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
{
window.location.href='sessionExpired.html'; //whatever
}
}
}
$(document).ajaxComplete(checkSession)
I found a feature to check if your call has been redirected. It's xhr.state(): if it's "rejected" then a redirection happened.
Example with success callback:
request.success(function(data, textStatus, xhr)
{
if(xhr.state() == "resolved")
{
//no redirection
}
if(xhr.state() == "rejected")
{
//redirection
}
});
Example with error callback:
request.error(function(xhr, textStatus)
{
if (xhr.state() == "rejected")
{
//redirection
location.href = "loginpage";
} else
{
//some other error happened
alert("error");
}
});
I can't possibly add to the insightful wisdom of the previous coders who've responded, but I will add a specific case that others may find useful to know about.
I came across this 302 silent redirect in the context of SharePoint. I have some simple Javascript client code that pings a SharePoint sub-site, and if it receives a 200 HTTP response, it relocates to that site, via window.location. If it receives anything else, it gives the user a notice that the site doesn't exist.
However, in the case where the site exists but the user does not have permission, SharePoint silently redirects to an AccessDenied.aspx page. SharePoint has already done the HTTP 401 authentication handshake at the server/farm level - the user has access to SharePoint. But the access to the sub-site is handled I suppose using database flags of some sort. The silent redirect bypasses my "else" clause, so I can't throw up my own error. In my case, this is not a show-stopper - it is consistent predictable behavior. But it was a little surprising, and I learned something about HTTP requests in the process!
I was interested in the same thing and could not find the state() method mentioned by Takman and did a little digging for myself. For the sake of people turning up here in search of an answer, here are my findings:
As stated multiple times, you cannot prevent redirects, but you can detect them. According to MDN you can use the responseURL of the XMLHttpRequestObject, which will contain the final URL the response came from, after all redirects. Only caveat is that it is not supported by Internet Explorer (Edge has it). Since the xhr/jqXHR passed into the success/done function of jquery is an extension of the actual XMLHttpRequest, it should be available there, too.
While it is not possible to disable location redirect following in XmlHttpRequests, it is when using fetch():
fetch('url', {redirect: manual});
I suppose you receive a 200 response because the second time there is no redirection, because the 404 page does not expire, it is saved in the cache. That is to say that the second time the browser gives you the page in the cache.
There is a property "cache" in the ajax jquery.
http://api.jquery.com/jQuery.ajax/
You should write it to "false"
I'm not sure if this will apply in your case, but you can write code to respond to specific status codes in AJAX function -
$.ajax({
url: '/admin/secret/data',
type: 'POST',
contentType: 'application/json; charset=utf-8',
statusCode: {
200: function (data) {
alert('302: Occurred');
// Bind the JSON data to the UI
},
401: function (data) {
alert('401: Occurred');
// Handle the 401 error here.
}
}
});
In the request headers in the case of ajax request you will have the following
X-Requested-With XMLHttpRequest
By this criteria on the server side you can filter requests.
I'm implementing a Web service that returns a JSON-encoded payload. If the service call fails -- say, due to invalid parameters -- a JSON-encoded error is returned. I'm unsure, however, what HTTP status code should be returned in that situation.
On one hand, it seems like HTTP status codes are for HTTP: even though an application error is being returned, the HTTP transfer itself was successful, suggesting a 200 OK response.
On the other hand, a RESTful approach would seem to suggest that if the caller is attempting to post to a resource, and the JSON parameters of the request are invalid somehow, that a 400 Bad Request is appropriate.
I'm using Prototype on the client side, which has a nice mechanism for automatically dispatching to different callbacks based on HTTP status code (onSuccess and onFailure), so I'm tempted to use status codes to indicate service success or failure, but I'd be interested to hear if anyone has opinions or experience with common practice in this matter.
Thanks!
http status code are just for indicating the status of the application response.
and as you said, if json parameters as somehow invalid, a 400 status code is an appropriate answer.
so yes, it is a really good idea to use http status code. de plus, status code are then easy to understand as they don't change from an application (web services) to another
You should definitely use the proper status codes since they are exactly for this purpose, not to indicate the status of the HTTP request itself. By this way you can redirect the response to the appropriate function/branch before parsing it which will lead to a much tidier code in the client side.
I use jQuery to make an AJAX POST request to my server, which can return HTTP response with status 302. Then JavaScript just sends GET request to this URL, while I'd like to redirect user to URL in this response. Is this possible?
The accepted answer does not work for the reasons given. I posted a comment with a link to a question that described a hack to get round the problem of the 302 being transparently handled by the browser:
How to manage a redirect request after a jQuery Ajax call
However, it is a bit of a dirty hack and after much digging around I found what I think is a better solution - use JSON. In this case, you can make all responses to ajax requests have the code 200 and, in the body of the response, you add some sort of JSON object which your ajax response handler can then use in the appropriate manner.
I don't think so. The W3C says that HTTP redirects with certain status codes, including 302, must be transparently followed. Quoted below:
If the response is an HTTP redirect (status code 301, 302, 303 or
307), then it MUST be transparently followed (unless it violates
security or infinite loop precautions). Any other error (including a
401) MUST cause the object to use that error page as the response.
As an experiment, I tried doing Ajax requests from various browsers (Firefox 3.5, Chrome, IE8, IE7, IE6) to a server giving a 302 status code, and showing the status in the browser's request object. In every case, it showed up as 200.
In my problem reason was:
i was using localhost/Home/Test addres for testing the page. But ajax request code using 127.0.0.1/Home/AjaxRequest for url parameter. When the urls are different this error occurs.
maybe it helps someone :)
Rather than asking the Javascript code to Handle 302, it would be better to return a 500 with custom error code+ message on event of 302
function doAjaxCall() {
$.ajaxSetup({complete: onRequestCompleted});
$.get(yourUrl,yourData,yourCallback);
}
function onRequestCompleted(xhr,textStatus) {
if (xhr.status == 302) {
location.href = xhr.getResponseHeader("Location");
}
}