Where to make write requests for resources that return 303 for retrieval?
Opened this issue · 10 comments
e.g. /foo 303's to /bar - some WebIDs do this.
Where should client perform write operations? /foo or /bar?
Should there be a link relation in the header of /bar to /foo (or somewhere else)?
Is this well-documented somewhere e.g. in the depths of https://www.w3.org/wiki/Foaf%2Bssl ?
Examples from the wild would be good to know..
There is a related requirement in the Solid Protocol: write requests on representation URLs when different from the resource URL are to 307/308 to the original resource.
When there is a write request on the final URL (after 303,.. the eventual 200), we can't ask the client to re-issue the request against the original resource since that would get stuck in 303->307/308->303.
Requests to the original resource returning different responses depending on request's method - 303 for GET/HEAD, and either 200 or 307/308 for PUT/POST/PATCH - doesn't seem right to me either.
Should we expect/suggest the client to make their write requests to /bar?
@csarven TrinPod uses a 303 redirect from webid in the form: https://user.trinpod.us/i to https://user.trinpod.us/profile/card . OPTIONS, HEAD and GET do the 303 redirect, but there is no redirect with POST PATCH PUT DELETE
The architecture of the web is that you read write documents, not people. Typically we use the #
to separate the URI of the document from the identifier of the (say) person within that file. You can write to the document, but writing to the person isn't a thing.
It seems to me the logical thing to do with the 303, when there is a 303 redirect from the Person to their profile, to prevent the write to the Person URI, as the agent should write the information about the person to the profile document.
You certainly should not overwrite the profile document.
Some context worth considering here:
- From the browser, via the
fetch()
API, there is no way to get information about redirects; you can either get the information about the final resource, or no information at all. This means onGET /username
that we cannot distinguish between types of redirect (303, 308, 307, etc). - There is likely a semantic difference between a 303 redirect (see other) and a 308 (permanent redirect)
Given these two points, from the client-side, all redirects are the same: there is simply no way to handle them differently.
If GET /username
would result in a 303, should OPTIONS /username
return a 200? Or should they both result in 303 redirects to the same place?
Currently we have OPTIONS /username
returning 200 with headers that say "yes, this is editable", however GET /username
results in a final response URL of /username/lookup
which if persisted, would result in writes failing.
@ThisIsMissEm Yes, you can get full header information from the fetch() API on the browser side by looking at the headers.
If you set a variable and await the fetch, such as:
const response = await fetch(...)
you can then access the headers via:
response.headers.get('nameOfHeader')
and for status simply
response.status
which is 303 on a redirect so to check for eTag value, you would use
response.headers.get('eTag')
and to know if the url has been redirected compare:
response.url to the request url to see if different
@timbl If we take the definition of a resource as currently defined, then a resource can be many things. In our case, we have a card resource that contains ( http://semanticscience.org/resource/SIO_000202 a more generic contains than ldp:contains) the webid resource such that when a request is made on card, it also delivers the webid resource. The webid resource is also a resource and can be separately accessed via POST PATCH PUT DELETE, but it always redirects to card on GET, HEAD and OPTIONS per Solid spec.
Then we have even a finer grained resource which is a single triple with its own uri, such that we can separately attach acl permissions to different triples on the webid. The idea being that the webid is source of all information about a given person (if its a personal webid), and that a person has an enourmous amount of information about themselves to which they would like to be the subject of a triple. I'm not sure how this is not consistent with the resource architecture of the web?
@gibsonf1 unfortunately not, for 3xx responses, the fetch API automatically follows redirects, only allowing access to the final destination's information, and in manual mode, prohibits accessing the redirect's headers or status code; so you can't detect the difference between a 303 redirect and a 308 redirect.
- https://fetch.spec.whatwg.org/#ref-for-concept-response-status%E2%91%A0%E2%91%A0
- https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect
For redirects the information about the status, headers, and body is removed from the result returned from fetch. I've
verified this result in both Firefox and Chrome: (I've had to remove the URL from the screenshot as it's on a non-public server, but have no doubt that it does return a 303 redirect)
There's also an issue on the fetch API spec to add a feature to allow access, but it's not moved in several years: whatwg/fetch#601
@ThisIsMissEm I see you are right on the status issue, although knowing what url you end up at is easy with response.url. So for the Solid case, maybe the simple solution since fetch is not quite up to it yet is to just add a header indicating the redirect.
@ThisIsMissEm I see you are right on the status issue, although knowing what url you end up at is easy with response.url. So for the Solid case, maybe the simple solution since fetch is not quite up to it yet is to just add a header indicating the redirect.
Right so, you can know that you've been redirected, via response.redirected
, but you can't know what sort of redirect, so all 3xx redirects look the same to the client. As for a header, the server can't tell that the request for the path that you're redirected to was from a redirect, so the header would need to be present on all responses for that path.
@ThisIsMissEm Yes, I think the answer to this is to include a header for redirect in the spec.