Appropriate error response body for CSV
-
Hey, a quick question. Let's say customer clicks on a "Download CSV" link, but there is an error on the backend. I'll obviously set the HTTP status, but what's the appropriate response body?
If I do nothing special, they'll just get the usual JSON payload which seems crappy. Should I send a special error CSV? If so, user might be confused at getting a different CSV than they expected. Or maybe send an empty body?
Dunno. What do you think?
-
@cartman82 empty
-
Can you not just send an error page/dialog saying that there was an error (and elaborating as appropriate)?
-
@cartman82 the nginx way - put enough spaces that the algorithm detecting empty response gives up and and doesn't put their own shit in there.
That, or stop the JSON injector from injecting that JSON.
-
@kazitor said in Appropriate error response body for CSV:
Can you not just send an error page/dialog saying that there was an error (and elaborating as appropriate)?
Well, I would point user's browser towards the download CSV link, so whatever happened there would have to happen outside my SPA. I guess I could switch to HTML and display an error page, but I would have to recreate a lot of context user is expecting to see (design aesthetics, language they picked...). Dunno if it's worth the trouble...
-
@Gąska said in Appropriate error response body for CSV:
@cartman82 the nginx way - put enough spaces that the algorithm detecting empty response gives up and and doesn't put their own shit in there.
I am not up to speed, what would I be trying to achieve with this?
-
@cartman82 It's out of my personal experience, but could the download link send some simple JSON response (perhaps with appropriate headers) upon error, and some JavaScript attached to the download link is somehow able to determine whether it received a file or error?
-
@cartman82 said in Appropriate error response body for CSV:
@Gąska said in Appropriate error response body for CSV:
@cartman82 the nginx way - put enough spaces that the algorithm detecting empty response gives up and and doesn't put their own shit in there.
I am not up to speed, what would I be trying to achieve with this?
It sounded like your only reservation against returning empty response was that empty response gets replaced by stupid JSON. As in, if it didn't do that, there wouldn't even be a question what to do.
-
@kazitor said in Appropriate error response body for CSV:
@cartman82 It's out of my personal experience, but could the download link send some simple JSON response (perhaps with appropriate headers) upon error, and some JavaScript attached to the download link is somehow able to determine whether it received a file or error?
Not directly. The issue is that download is basically treated not as AJAX, but as a completely separate request. So there is no javascript on the other end, just pure browser (or curl/telnet/whatever) client getting an HTTP message.
What I could do (and I did a few times before) is have a two-step process. One JSON request to "prepare" the download, and this returns either the usual error payload or the download link. The browser is then redirected to the download link, which is handled like a static asset (cached somewhere on server HDD, for example).
-
@Gąska said in Appropriate error response body for CSV:
It sounded like your only reservation against returning empty response was that empty response gets replaced by stupid JSON. As in, if it didn't do that, there wouldn't even be a question what to do.
No, I meant if I didn't do anything special, my web app would return JSON by default. I can totally replace it with empty body on my end.
-
@cartman82 said in Appropriate error response body for CSV:
What I could do (and I did a few times before) is have a two-step process. One JSON request to "prepare" the download, and this returns either the usual error payload or the download link. The browser is then redirected to the download link, which is handled like a static asset (cached somewhere on server HDD, for example).
That's what I would assume would be done. The question is what extent of is present.
-
@kazitor said in Appropriate error response body for CSV:
What I could do (and I did a few times before) is have a two-step process. One JSON request to "prepare" the download, and this returns either the usual error payload or the download link. The browser is then redirected to the download link, which is handled like a static asset (cached somewhere on server HDD, for example).
That's what I would assume would be done. The question is what extent of is present.
That was kind of PITA the last time I did it. I needed to handle half-saved corrupted files, TTL, cleanup... Necessary if it can potentially take more than 5 seconds to generate a report, but PITA nonetheless.
If I can get away with an empty body and direct CSV response, I'll totally go for that.
-
I believe what we just return an HTTP 409 Conflict status and put HTML as content. If the
Content-Type
header doesn't containapplication/octet-stream
and there's noContent-Disposition
the browser should realize it's not a download.In some cases we put in a redirect to an error page (mostly through the
meta
element technique) so that we can handle the error in a new instance of the SPA.
-
@cartman82 said in Appropriate error response body for CSV:
@Gąska said in Appropriate error response body for CSV:
It sounded like your only reservation against returning empty response was that empty response gets replaced by stupid JSON. As in, if it didn't do that, there wouldn't even be a question what to do.
No, I meant if I didn't do anything special, my web app would return JSON by default. I can totally replace it with empty body on my end.
You're making a very strong distinction between "my web app" and "my end" that I don't quite get. Are you in control of both frontend and backend? If so, then you need to fix the frontend so it handles error correctly. If not, then you need to find a workaround that tricks the frontend to do the closest thing to expected behavior - to which, there is not a single right answer, as it depends on particular quirks of the frontend that nobody on this forum is familiar with.
-
@Gąska said in Appropriate error response body for CSV:
If so, then you need to fix the frontend so it handles error correctly.
Downloads are special and should be definately called labelled "legacy" when you need to do it from a SPA.
What you tend to do in your frontend is that you tell the browser "Open this URL (in a new tab or current page)" and the browser will do the GET request to that URL. Once it sees that the response's
Content-Type
andContent-Disposition
header are filled in it will show a "Save File As" dialog and your download is managed by the browser's Download Manager. The frontend is at that point no longer in control though, the browser is handling the GET call on its own and will show any error JSON you return from the download URL. No JavaScript gets called for the response.
The only thing I haven't seen mentioned in this thread is what some file-sharing websites (used to) do: bypassing the browser's download manager by never just handing off the download URL. Instead they seemed to download the file to local storage using some HTML 5 API, and when that was done they would show a button "Save" to pop up the "Save as" dialog when you clicked it. Basically they made their own JS-only download manager.
No idea how this worked internally, and it will obviously not work if you need to support a crusty HTML 4 browser...
-
@JBert said in Appropriate error response body for CSV:
@Gąska said in Appropriate error response body for CSV:
If so, then you need to fix the frontend so it handles error correctly.
Downloads are special and should be definately called labelled "legacy" when you need to do it from a SPA.
What you tend to do in your frontend is that you tell the browser "Open this URL (in a new tab or current page)" and the browser will do the GET request to that URL. Once it sees that the response's
Content-Type
andContent-Disposition
header are filled in it will show a "Save File As" dialog and your download is managed by the browser's Download Manager. The frontend is at that point no longer in control though, the browser is handling the GET call on its ownSo far so good...
and will show any error JSON you return from the download URL.
But why would you return error JSON in the first place, if returning error JSON is not what you want? (I assume returning error JSON isn't what @cartman82 wants.)
-
-
If the client only
Accept:
stext/csv
, an empty reply should suffice. Otherwise, if rendering a proper HTML error page is too much trouble, a plain text error message should be enough.On second thought, perhaps I would try to redirect to a special error page, possibly passing the error message in the parameters.
-
Interesting. What is the solution so far?
-
@JBert said in Appropriate error response body for CSV:
I believe what we just return an HTTP 409 Conflict status and put HTML as content.
???
How is this in any way, shape, or form a client side (400 series) error?
-
@JazzyJosh It depends on context of course, we use 409 when another status call returning JSON should have made it clear that the file isn't available for download because it's still processing.
If the error on the backend was caused by e.g. a template file which got corrupted than a 500 would of course be required.
-
@cartman82 said in Appropriate error response body for CSV:
send an empty body?
They requested a file. File wasn't available due to problem. If 500,and you can satisfy sending the error based on Expect headers, do so. Otherwise, follow conventions for sending content (or not) if the request cannot be satisfied.
I'm pretty sure this is even in the HTTP spec...
-
@Tsaukpaetra I seem to recall some content types (
text/plain
?) are legal even if they're not in the expect headers for 300/400/500 codes.
-
@PleegWat said in Appropriate error response body for CSV:
@Tsaukpaetra I seem to recall some content types (
text/plain
?) are legal even if they're not in the expect headers for 300/400/500 codes.Doesn't really affect anything I said though, does it?
-
@Tsaukpaetra You mentioned "if you can satisfy sending the error based on the Expect headers". I'm pretty sure they don't apply.
-
@cartman82 said in Appropriate error response body for CSV:
@kazitor said in Appropriate error response body for CSV:
Can you not just send an error page/dialog saying that there was an error (and elaborating as appropriate)?
Well, I would point user's browser towards the download CSV link, so whatever happened there would have to happen outside my SPA. I guess I could switch to HTML and display an error page, but I would have to recreate a lot of context user is expecting to see (design aesthetics, language they picked...). Dunno if it's worth the trouble...
If you load the link in an iframe, you could skip all of the contextual stuff and just popup a Javascript alert instead of sending the CSV.
-
@cartman82 said in Appropriate error response body for CSV:
@Gąska said in Appropriate error response body for CSV:
@cartman82 the nginx way - put enough spaces that the algorithm detecting empty response gives up and and doesn't put their own shit in there.
I am not up to speed, what would I be trying to achieve with this?
Some browsers won't display HTTP status pages sent by the server if the response body is too short. IE has traditionally been a major guilty party in doing this. If the response body is long enough, then it displays that, containing the actual HTTP error page from the server. Otherwise, it just displays a generic "friendly" error page.
The error page it displays is a little more friendly than 404 NOT FOUND, but not by a whole lot, and it overrides your custom HTTP error page. The workaround is to add a bunch of filler, e.g. space characters or a HTML comment tag, to your custom HTTP error page, making the response body large enough that IE displays it instead of overriding it.
-
@anotherusername But don't do that to force showing an error page that is no friendlier than 404 NOT FOUND.
-
@JBert said in Appropriate error response body for CSV:
The only thing I haven't seen mentioned in this thread is what some file-sharing websites (used to) do: bypassing the browser's download manager by never just handing off the download URL. Instead they seemed to download the file to local storage using some HTML 5 API, and when that was done they would show a button "Save" to pop up the "Save as" dialog when you clicked it. Basically they made their own JS-only download manager.
No idea how this worked internally, and it will obviously not work if you need to support a crusty HTML 4 browser...It's called
Blob
.This is a pretty interesting example of how it can be used:
-
The correct response is
HTTP STATUS : "DONALD TRUMP".
You then base63 encode (because base64 is too mainstream) because the Russian are watching.
-
@pie_flavor said in Appropriate error response body for CSV:
Yes, that name rings a bell, must have been that one.
-
@anotherusername said in Appropriate error response body for CSV:
The workaround is to add a bunch of filler, e.g. space characters or a HTML comment tag, to your custom HTTP error page, making the response body large enough that IE displays it instead of overriding it.
You must be fucking kidding me! Wow!
-
@anotherusername said in Appropriate error response body for CSV:
@cartman82 said in Appropriate error response body for CSV:
@Gąska said in Appropriate error response body for CSV:
@cartman82 the nginx way - put enough spaces that the algorithm detecting empty response gives up and and doesn't put their own shit in there.
I am not up to speed, what would I be trying to achieve with this?
Some browsers won't display HTTP status pages sent by the server if the response body is too short. IE has traditionally been a major guilty party in doing this. If the response body is long enough, then it displays that, containing the actual HTTP error page from the server. Otherwise, it just displays a generic "friendly" error page.
The error page it displays is a little more friendly than 404 NOT FOUND, but not by a whole lot, and it overrides your custom HTTP error page. The workaround is to add a bunch of filler, e.g. space characters or a HTML comment tag, to your custom HTTP error page, making the response body large enough that IE displays it instead of overriding it.
wonder if just setting a content-length works
-
@Gribnit no.
-
@stillwater said in Appropriate error response body for CSV:
@anotherusername said in Appropriate error response body for CSV:
The workaround is to add a bunch of filler, e.g. space characters or a HTML comment tag, to your custom HTTP error page, making the response body large enough that IE displays it instead of overriding it.
You must be fucking kidding me! Wow!
Nope. Apparently the minimum is 512 bytes.
Another workaround is to just leave the HTTP status set to
200 OK
(or something that isn't one of the codes listed on that IEInternals page). Then the browser will display the error page, regardless of how large it is. But then you run the risk of confusing web robots and the like.
-
@anotherusername said in Appropriate error response body for CSV:
@stillwater said in Appropriate error response body for CSV:
@anotherusername said in Appropriate error response body for CSV:
The workaround is to add a bunch of filler, e.g. space characters or a HTML comment tag, to your custom HTTP error page, making the response body large enough that IE displays it instead of overriding it.
You must be fucking kidding me! Wow!
Nope. Apparently the minimum is 512 bytes.
Another workaround is to just leave the HTTP status set to
200 OK
(or something that isn't one of the codes listed on that IEInternals page). Then the browser will display the error page, regardless of how large it is. But then you run the risk of confusing web robots and the like.204 NO CONTENT
seems vaguely appropriate. But it's not an error. You could I suppose not sent the content-disposition in the case of the error response? Then at least they don't download garbage.
-
@JBert said in Appropriate error response body for CSV:
we use 409 when another status call returning JSON should have made it clear that the file isn't available for download because it's still processing.
Ok, that makes more sense. From your context I was assuming user clicked download button and you choked during processing of the download.
-
I ended up doing the 2-step solution I said was pain in the ass.
Initial request prepares the CSV and saves it to cache. Client gets a JSON message in the usual format, containing link to the unauthenticated endpoint serving CSV-s (using one-off token for security). It then immediately opens the link, initiating download.
This setup takes care of a few issues stated in the thread above (validation, errors) and a few unstated ones (passing security token). Since I don't predict mammoth CSV downloads in the near future, I am just keeping the CSV content in server RAM, which makes implementation less of a PITA than I feared.
In case the download link produces an error (much less likely than the initial request), I generate a simple HTML body and send that back instead of the CSV. The api codebase isn't really geared up for producing HTML, but I figure this use case is rare enough that I don't need to optimize for it.
-
@cartman82 said in Appropriate error response body for CSV:
The api codebase
Well at least you're using one?
-
@Tsaukpaetra Called via CGI I presume? :)
-
@cartman82 said in Appropriate error response body for CSV:
@Tsaukpaetra Called via CGI I presume? :)
Nope, raw socket IO.