3

By default, Servant returns plain string requests even if the requested endpoint returns JSON

$ http $S/signup email=mail@domain.com
HTTP/1.1 400 Bad Request
Connection: keep-alive
Date: Tue, 14 Apr 2020 15:59:32 GMT
Server: nginx/1.17.9 (Ubuntu)
Transfer-Encoding: chunked

Error in $: parsing Credentials.Credentials(Credentials) failed, key "password" not found

I am trying to wrap such strings into simple JSON dictionaries:

$ http $S/signup email=mail@domain.com
HTTP/1.1 400 Bad Request
Connection: keep-alive
Date: Tue, 14 Apr 2020 15:59:32 GMT
Server: nginx/1.17.9 (Ubuntu)
Transfer-Encoding: chunked

{"error": "Error in $: parsing Credentials.Credentials(Credentials) failed, key \"password\" not found"}

But it looks like it's not that easy.

This question states possible solutions but I can't make them work today Custom JSON errors for Servant-server

Another approach is discussed in this thread https://github.com/haskell-servant/servant/issues/732 but it looks like overkill to such a simple task.

I wonder if there is a simple and robust solution in 2020?

Nik
  • 9,063
  • 7
  • 66
  • 81

1 Answers1

4

There is a library called servant-errors. It provides a middleware that does exactly what you are looking for – transforms error responses to have a uniform structure of your choice, JSON being one of the built-in options.

See the documentation for details, but the basic usage is as straightforward as wrapping

errorMw @JSON @["error", "status"]

around your appilcation.

kirelagin
  • 13,248
  • 2
  • 42
  • 57
  • Thanks, works fine for parsing errors but for database errors, I still get plaintext `Something went wrong` response. Do you know if it's possible to convert all internal errors to `JSON`? – Nik Apr 15 '20 at 21:08
  • 1
    This middleware only modifies responses with error codes > 200 and with no Content-Type header, so if your errors have wrong HTTP status or set Content-Type, that can cause them not to be rewritten. Another possible option is that the error is thrown through a middleware applied _before_ this one. – kirelagin Apr 16 '20 at 10:31