feathers
feathers copied to clipboard
Avoid automated json conversion when using fetch
From @eric-burel on June 8, 2018 8:32
Hi,
I noticed that the fetch service always does a response.json(), however in many case you might need another conversion (e.g response.blob() for files). For the moment, reading the code, I think this can't be configured (tell me if I am wrong though), that could be a good enhancement.
However I wonder what would be the best pattern. Having response.json as a default makes sense, as it is consistent with other solutions (axios etc.).
The potential solutions:
- figuring out the best option depending on the mime type. I think it only partially solve the issue, as I could still want my image as a string and not a blob() for example, and would be tedious to implement.
- adding a custom parameter to tell
fetchwhat to use.responseTypeis a good candidate, as it would be consistent with XHR (so axios too and maybe other services).
Edit: actually I can't figure this out either for axios, the responseType does not seem to be customizable.
Edit 2: okay I figured out your last commit now allow this for Axios, I needed to update the lib.
Copied from original issue: feathersjs/rest-client#32
As you mentioned, some libraries allow customizing the settings through params.connection (or additionally request.defaults for requests). Since the default request type is application/json, converting JSON back usually makes sense.
For downloads, I'm not even sure if it makes sense to be able to use the client. When I'm serving downloadable content (through the Content-Disposition header) I usually just use a plain <a href="/link/to/service" target="_blank">Download</a> link that people can click.
From @eric-burel on June 8, 2018 17:7
Hi, thanks for your feedback. Will you enjoy authentication when using a link, given that the auth token is stored in the localStorage ? Also you lose a bit of consistency, using the feathers client feels better when the query is complex. Here I need to dynamically generate the file (a zip of multiples .csv) given a set of parameters, so using a link in the html feels weird.
Maybe I could write a short tutorial for this specific use case if that can help future users.
But anyway I did not figure out how you would configure the fetch client to handle blobs in the general case. Of course this is not a very important feature, but still make using fetch with feathers-client less powerful than other tools while fetch is going to be the next standard.
True, you'd have to add the token as a query parameter. How would the request and download look using plain fetch? I'm not opposed to making the .json() call optional (depending on the Accept request header or Content-Type response header). It's probably the right way to do it anyway.
From @eric-burel on June 9, 2018 20:38
Using fetch and the FileSaver lib you will simply write something like
fetch('my-file')
.then(res => res.blob())
.then(blob => FileSaver.saveAs(blob, "myzip.zip")
Yeah I think this is the correct solution. If Content-type is not application/json and fetch is the request engine then we can guess that the user is wanting to achieve a custom behaviour, so it becomes his responsibility to handle/convert the result or to use a more powerful lib instead of fetch, and the res should be returned without additionnal changes.
Also, it makes me think that exposing some url building features (getting the auth token for exemple and setting it in the query) would be really cool. This way I could have written something like (with React):
<a href={ myService.urlBuilder.find({query: { foo:"bar"}) }>Download the file</a>
This would be even better for this use case, it would let the browser handle the file download while using a frontend friendly and consistent API.