- From: Jonas Sicking <jonas@sicking.cc>
- Date: Thu, 5 Mar 2009 01:18:39 -0800
- To: Anne van Kesteren <annevk@opera.com>
- Cc: Webapps WG <public-webapps@w3.org>
>> What about the following scenario: >> 1. A page on site A initiates a DELETE request to a uri on site B >> 2. The UA makes a preflight OPTIONS request to the uri on site B >> 3. The site responds and says the original DELETE request is ok >> 4. The UA makes the DELETE request to site B >> 5. The site responds with a 303 that redirects to a different uri on site >> B. > > Network error steps. > > >> Should this redirect not be followed even though it technically does >> not require a preflight? > > Correct. All redirects on the actual request fail. I don't think that is desirable nor necessary, see below. >> I think it's fairly important that we do follow the redirect since a >> common way to deal with state changing requests is to redirect to a >> URI that contains the response. This avoids ugly "you have to refresh >> to display this page" pages in browsers. So I think the redirect >> should be followed. > > Why would there be no redirect on the OPTIONS request? It's very possible for a server to serve different redirects for different request methods. My understanding of the HTTP spec is that a 303 response is meant to mean that the current uri has handled the request, but that the response is located at a different uri. For normal browser navigation this is the recommended way to, for example, allow a POST to a shopping cart that adds an item to the shopping cart, while still allowing the user to navigate back to the result page without worrying about another item being added to the shopping cart. A POST is performed to a uri that adds the desired item, but then uses a 303 response to redirect the user to the page that actually displays the shopping cart. If the user then navigates away from that page, and then back to it, it'll still result in a safe GET request to the uri that displays the shopping cart, without adding any additional items to it. So this is quite a common pattern on the web today, and ideally should be more common. Rather than using the state-changing GET requests sites do today to avoid having to deal with the ugly "you need to refresh to display this page again" error pages that browsers produce from un-redirected POST requests. For this setup it makes a lot of sense to not redirect a OPTIONS request, but to redirect a POST request to the same uri. >> What should be done in the following scenario: >> 1. A page on site A initiates a DELETE request to a uri on site B >> 2. The UA makes a preflight OPTIONS request to the uri on site B >> 3. The site responds with a 303 to a different uri on site B. > > Currently the specification treats all redirects the same. I guess we could > special case 303. In the setup described above, even if the server redirects the add-item-to-cart OPTIONS response to the display-shopping-cart uri, it makes little sense to redirect the POST there. That would never have happened for a same-site POST request going to the add-item-to-cart uri. >> Should perhaps >> a 303 redirect mean that the DELETE request should be made to the >> initial uri on site B, assuming that the preflight after redirects >> ended up returning a response with the appropriate headers? > > No, that seems wrong. Why? A 303 just means that the response is located elsewhere, not that the action is performed by a different uri. >> I don't have strong opinions on this one. But a gut feeling is that >> only a 307 should cause the DELETE to go somewhere else as that is the >> only time when that would have happened if the DELETE would have been >> done directly to the first uri on site B. > > 301 and 302 should do that too. Why? Note that 302 is basically treated as a 303 by most browsers today just because what the spec says is basically terrible UI asking the user to make a decision he/she does not have enough information to make. More below. >> And here's another: >> 1. A page on site A initiates a POST request to a uri on site B. The >> request is >> a entity body and a Content-Type of "text/plain" >> 2. Since no preflight is needed The UA makes the request to the uri on >> site B >> 3. Before the server has responded, the page adds a event listener for the >> progress event on the upload object. (This listener won't be >> notified according >> to spec) >> 4. The server responds with a 307 redirect to another URI on site B. >> >> Should the request to the new URI on site be now be done with a >> preflight? Or should the algorithm abort because a preflight is now >> required but there is a redirect. Or should the redirect be followed >> but the event listener not be notified? In other words, should the >> fact that there is upload event listeners be measured on just the >> initial request, or on each redirect. >> >> I think the fact that there is upload event listeners should be >> measured just on the initial request. So in the example above the >> redirect should be followed but no events would be fired on the upload >> object. > > I think this is already clear in the specification. My understanding is that the answer is that it's only measured in the beginning. Is this correct? >> The following scenario might be gecko-specific: >> 1. A page on site A initiates a POST request to a uri on site B. The >> request is >> not given a body, but is given a Content-Type of "text/plain" >> 2. Since no preflight is needed The UA makes the request to the uri on >> site B >> 3. The server responds with a 307 redirect to another URI on site B. >> >> In this case Gecko creates a new request that doesn't have a >> Content-Type header since there is no body. I suspect this is Gecko >> specific behavior though and so nothing that needs to be addressed >> specifically. Would be interesting to hear if other browsers have the >> same behavior though. > > That seems like a bug. I will investigate further. >> So to sum things up. I suggest the following behavior: >> * When the actual request (i.e. not a preflight request) is done, only >> abort with a network error if the newly created request would require >> a preflight. So don't abort in the case when the redirect changes the >> request from one that requires a preflight into one that doesn't. >> (This means that in the gecko-specific case above, abort with a >> network error since the newly createde request does require >> preflight). > > This case seems so marginal that it does not seem worth the complexity to > me. It only ever occurs in case of 303 where the preflight request is not > redirected for whatever reason. As described above, it is in fact the recommended way to allow the UA to fetch the response to the request multiple times without causing the action to happen every time. So there are several servers out there that behave this way already, and once we add support for redirects to XHR, it's most likely something that developers will want to do in XHR as well. >> * When making the OPTIONS preflight request, only change the >> destination uri of the actual request if the response is a 307. > > Why not for 301 and 302? In my examples I've used 303 and 307 as they are the most unambigios redirections. 302 is generally treated as 303, though the spec allows it to be treated as a 307 after asking for user permission. I'm unclear on how 301s are supposed to work, but at least in gecko they do seem to behave like a 303, though with some effect on following requests that I haven't yet dug in to (which is what sets them, as permanent redirects, apart from temporary redirects). In short, I think the spec currently misunderstands the HTTP protocol by treating all redirects as redirects of the request, whereas many of them are just redirects of the response. / Jonas
Received on Thursday, 5 March 2009 09:19:19 UTC