如何使用Network.HTTP.receiveHTTP在Haskell中编写简单的HTTP服务器

Son*_*raj 14 haskell http

该模块Network.HTTP 暴露功能receiveHTTPrespondHTTP我想使用一个非常基本的Web服务器.我写了一个等待客户的存根:

{-# 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)
Run Code Online (Sandbox Code Playgroud)

这里accpet给了我Handle,现在我无法弄清楚如何使用HandlereceiveHTTP.

我找到谷歌的一个例子,但它是从2008年开始的,不再适用了.我无法移植它.

有任何想法吗?

Ech*_*lan 6

你可以这样做,但我真的认为你不应该这样做.HTTP可以充当服务器,但设计用于客户端.我用Google搜索了一下,我找不到任何实际使用过的人的例子respondHTTP.如果您在2016年使用客户端HTTP http-conduit.在服务器端,warp或依赖它的东西可能是你想要的.

不过,这是代码.

#!/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
Run Code Online (Sandbox Code Playgroud)

以上使用Stack对shebang脚本的支持.chmod +x它或运行它stack foo.hs.

Network模块已弃用.Network.Socket如果需要套接字API,请始终使用.对于更高级别的东西,请使用connection.

你做普通的POSIX套接字,然后将连接的套接字转换为HandleStreamwith 并在其上socketConnection运行.是一个奇怪的功能.前两个参数是主机名和运行服务器时未使用AFAICT的端口.respondHTTPreceiveHTTPsocketConnection

我用了RecordWildCards扩展名.它允许我Right (Request {..})在一个模式中写入,并在右侧包含记录的所有字段.


C. *_*ann 5

也许是希望你使用accept功能,从Network.Socket代替Network?这给了你一个Socket而不是一个Handle,你应该能够转换为receiveHTTP可以使用的形式.

通常情况下Handle直接使用会更好,但是这里的HTTP库会为你处理它,所以它需要更低级别的接口.

编辑:看了一下之后,看起来socketConnection功能Network.TCP就是你所需要的.有趣的是,它实际上是在将套接字Handle从内部读取之前将其置于内部,但似乎并未提供从外部提供的读取方式Handle.该函数的字符串参数应该是远程主机的名称,但它看起来只是保留供参考; 它实际上并没有启动与该主机或任何东西的连接.