Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I return a ByteString from a Handler in Yesod?

I'm trying to return a ByteString from my Handler function in Yesod:

getHomeR :: Handler ByteString
getHomeR = return "foo"

but I'm getting this error:

/Users/maximiliantagher/Documents/Mercury/hs/mercury-web-backend/src/Application.hs:48:1: error:
    • No instance for (ToTypedContent ByteString)
        arising from a use of ‘yesodRunner’
    • In the expression:
        yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
      In a case alternative:
          "GET"
            -> yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
      In the expression:
        case Network.Wai.Internal.requestMethod req1404_axwf of {
          "GET"
            -> yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
          _ -> yesodRunner
                 (void badMethod) env1404_axwe (Just HomeR) req1404_axwf }

Why is this happening and why doesn't ByteString have a ToTypedContent instance?

like image 567
MaxGabriel Avatar asked Dec 15 '17 18:12

MaxGabriel


1 Answers

The ToTypedContent class describes what the content-type is of the data. So types that have an associated content type (e.g. UTF 8 for Text or Value (JSON)) can have a natural ToTypedContent instance.

The problem with ByteString is that it describes any binary data—your ByteString could be a PNG, a JPEG, or anything, so it's unclear what content type to give it.

If you really just want to return binary data, the octet-stream content type is appropriate:

getHomeR :: Handler TypedContent
getHomeR = return $ TypedContent typeOctet $ toContent ("x" :: ByteString)

But you should try for a better content type if possible (e.g. image/jpeg for JPEG).

In that case, you can either use the TypedContent manually as above, or write your own instance of ToTypedContent for a newtype over ByteString

newtype Jpeg = Jpeg ByteString deriving (Show, ToContent)

instance ToTypedContent Jpeg where
    toTypedContent h = TypedContent "image/jpeg" (toContent h)
like image 147
MaxGabriel Avatar answered Oct 22 '22 17:10

MaxGabriel