15

The module Network.HTTP exposes the functions receiveHTTP and respondHTTP which I'd like to use for a very basic web server. I wrote a stub that just waits for clients:

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Network.HTTP
import Network
import Control.Monad

main = withSocketsDo $ do
  socket <- listenOn $ PortNumber 8080
  forever $ do
    (handle, host, port) <- accept socket
    print (host, port)

Here accpet gives me a Handle, and now I can't figure out how to use a Handle with receiveHTTP.

I found an example with Google, but it is from 2008 and does not work anymore. And I was not able to port it.

Any ideas?

1
  • I can't directly answer this, but you might be able to find some helpful examples with Google Code Search. Commented May 27, 2011 at 20:54

2 Answers 2

8
+25

You can do this, but I really think you shouldn't. HTTP can act as a server, but is designed to be used client side. I Googled a little and I can't find any examples of someone actually using respondHTTP. If you're doing client side HTTP in 2016 use http-conduit. On the server side, warp or something that depends upon it is probably what you want.

Nevertheless, here's the code.

#!/usr/bin/env stack
-- stack --resolver lts-6.3 --install-ghc runghc --package HTTP
{-# LANGUAGE RecordWildCards #-}
import Control.Monad
import qualified Data.ByteString as B
import Network.HTTP
import Network.Socket
import Network.URI

main = do
  lsock <- socket AF_INET Stream defaultProtocol
  bind lsock (SockAddrInet 8080 iNADDR_ANY)
  listen lsock 1
  forever $ do
    (csock, _) <- accept lsock
    hs <- socketConnection "" 8080 csock
    req <- receiveHTTP hs
    case req of
      Left _ -> error "Receiving request failed"
      Right (Request {..}) -> if uriPath rqURI == "/"
                            then do
                              respondHTTP hs $
                                Response (2,0,0) "OK" [] "Hello HTTP"
                              Network.HTTP.close hs
                            else do
                              respondHTTP hs $
                                Response (4,0,4) "Not found" [] "Nothing here"
                              Network.HTTP.close hs

The above uses Stack's support for shebang scripts. chmod +x it or run it with stack foo.hs.

The Network module is deprecated. Always use Network.Socket if you need a socket API. For something higher level, use connection.

You do the normal POSIX socket thing, then convert the connected socket to a HandleStream with socketConnection and run respondHTTP and receiveHTTP on it. socketConnection is a weird function. The first two parameters are a hostname and a port which AFAICT aren't used when running a server.

I used the RecordWildCards extension. It lets me write Right (Request {..}) in a pattern and have all the fields of the record in scope on the right hand side.

Sign up to request clarification or add additional context in comments.

Comments

5

Perhaps it expects you to use the accept function from Network.Socket instead of Network? That gives you a Socket instead of a Handle, which you should be able to convert to a form that receiveHTTP can use.

Normally a Handle would be nicer to work with directly, but here the HTTP library is taking care of it for you so it expects the lower-level interface instead.

EDIT: After looking at it a bit further, it seems the socketConnection function in Network.TCP does what you need. The funny part is it's actually making the socket into a Handle internally before it reads from it, but doesn't seem to provide a way to read from an externally-provided Handle. The string parameter to the function is supposed to be the name of the remote host, but it looks like that's merely kept for reference; it's not actually initiating a connection to that host or anything.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.