Search code examples
jsonhaskellservant

How to force Servant return JSON errors instead of plain strings?


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

$ http $S/signup [email protected]
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 protected]
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?


Solution

  • 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.