0

I'm trying to write HTML to a page when a certain path is hit:

import Control.Monad
import Data.Char
import System.IO
import Network
import Data.Time.LocalTime

data RequestType = GET | POST deriving (Show)
data Request = Request { rtype :: RequestType, path :: String, options :: [(String,String)] }
data Response = Response { version :: String, statuscode :: Int }

instance Show Response where
    show r = version(r) ++ " " ++ show(statuscode(r)) ++ " " ++ (case statuscode(r) of
        100 -> "Continue"
        200 -> "OK"
        404 -> "Not Found") ++ "\r\n\r\n"

-- respond function
respond :: Request -> Handle -> IO ()
respond request handle = do
    putStrLn $ show request
    let response = Response {version = "HTTP/1.1", statuscode = 200}
    hPutStr handle $ show(response)
    hPutStr handle $ "Haskell says " ++ (getMessage request)
    where getMessage r
            | (path r) == "/hello" = "<b>hello there!</b>" <-- HERE
            | otherwise = (path r)

I can run this code without errors, but when I hit http://{hostname}/hello I get the string <b>hello there!</b> meaning the html is being rendered as a string.

How do I render it as html?

NOTE

I want to do this using vanilla Haskell, meaning no 3rd party libraries.

dopatraman
  • 13,416
  • 29
  • 90
  • 154

1 Answers1

0

You are not emitting a Content-type header. Without a Content-type header browsers will probably treat the output as plain text - not HTML.

If you change your code to emit:

HTTP/1.1 200 OK
Content-type: text/html; charset=UTF-8

Haskell says: <b>hello there!</b>

it should be rendered as HTML in your browser.

This SO answer has an example of a simple HTTP response containing HTML:

https://stackoverflow.com/a/26346025/866915

Update

Based on your code, this should work:

response :: Request -> Handle -> IO ()
response _ h = do
  hPutStr h "HTTP/1.1 200 OK\r\n"
  hPutStr h "Content-type: text/html; charset=UTF-8\r\n"
  hPutStr h "\r\n\r\n"
  hPutStr h "Haskell says: <b>hello there!</b>\n"

This assumes that you close the handle after emitting the response to indicate the end of the response. Also, note that your Show instance for the Response is not very helpful because you have to add more headers after the HTTP line but before the blank line.

If you post a link to your server code I can test this for you.

Community
  • 1
  • 1
ErikR
  • 51,541
  • 9
  • 73
  • 124
  • Answer updated - If you post a link to your server code I'll test this - otherwise I can only make assumptions about how response function is suppose to work. – ErikR Aug 24 '16 at 23:02
  • heres a link: https://gist.github.com/dopatraman/1573a20f53bf7c5a5d8b25cac9c9d82b – dopatraman Aug 25 '16 at 14:47
  • Doh! I used `text/plain` when I meant `text/html`. Answer verified to work now. – ErikR Aug 25 '16 at 15:06