Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I modify my code to return a custom JSON instead of just status 200?

Tags:

json

rest

haskell

I am trying to figure out how to implement basic auth with haskell/yesod and this is a basic implementation which works, referenced from similar questions.

module Handler.BasicAuth where

import Import
import Network.Wai 
import Network.HTTP.Types as Import
    ( status200 )

httpBasicAuth :: Handler ()
{-getBasicAuthR = error "Not yet implemented: getBasicAuthR"-}
httpBasicAuth = do
    request <- waiRequest
    case lookup "Authorization" (requestHeaders request) of 
        Just "Basic base64encodedusernameandpassword" -> return ()
        _ -> do
            addHeader "WWW-Authenticate" "Basic Realm=\"My Realm\""
            permissionDenied "Authentication required"

getBasicAuthR :: Handler ()
getBasicAuthR = httpBasicAuth >>
    sendResponseStatus status200 ()

I would like to modify my implementation to return not just http response code 200, but also a custom JSON that reads {"hello": "world"}.

How can I achieve this?

EDIT

As suggested by various people below, I should write getBasicAuthR as

getBasicAuthR :: Handler Value
getBasicAuthR = httpBasicAuth >> sendResponse $ object ["hello" .= "world"]

But this just gives me an error that says

Handler/BasicAuth.hs:27:17:
    Couldn't match expected type ‘Value -> Handler Value’
                with actual type ‘HandlerT App IO b0’
    The first argument of ($) takes one argument,
    but its type ‘HandlerT App IO b0’ has none
    In the expression:
      httpBasicAuth >> sendResponse $ object ["hello" .= "world"]
    In an equation for ‘getBasicAuthR’:
        getBasicAuthR
          = httpBasicAuth >> sendResponse $ object ["hello" .= "world"]

Handler/BasicAuth.hs:27:34:
    Couldn't match expected type ‘HandlerT App IO b0’
                with actual type ‘c0 -> m0 a0’
    Probable cause: ‘sendResponse’ is applied to too few arguments
    In the second argument of ‘(>>)’, namely ‘sendResponse’
    In the expression: httpBasicAuth >> sendResponse
like image 899
Calvin Cheng Avatar asked Dec 15 '14 10:12

Calvin Cheng


1 Answers

First, if you want respond with a JSON object, you would change the type of your handler. Since yesod-core uses aeson, the appropriate type is Handler Value:

getBasicAuthR :: Handler Value

Due to the monad laws, httpBasicAuth >> stays, but is followed by sendResponse (or sendResponseStatus 200) with an additional object:

getBasicAuthR = httpBasicAuth >> sendResponse (object ["hello" .= "world"])
like image 58
3 revs Avatar answered Oct 19 '22 23:10

3 revs