模块Network.HTTP
公开了我想用于非常基本的Web服务器的函数receiveHTTP
和respondHTTP
。我写了一个等待客户端的存根:
{-# 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)
此处accpet
为我提供Handle
,现在我无法弄清楚如何将Handle
与receiveHTTP
一起使用。
我在Google上找到了an example,但它是从2008年开始的,不再适用了。我无法移植它。
有什么想法吗?
答案 0 :(得分:6)
你可以这样做,但我真的认为你不应该这样做。 HTTP
可以充当服务器,但设计用于客户端。我用Google搜索了一下,我找不到任何实际使用respondHTTP
的人的例子。如果您在2016年使用http-conduit
进行客户端HTTP。在服务器端,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
以上使用Stack对shebang脚本的支持。 chmod +x
它或stack foo.hs
运行它。
不推荐使用Network
模块。如果需要套接字API,请始终使用Network.Socket
。对于更高级别的内容,请使用connection
。
您执行正常的POSIX套接字操作,然后将连接的套接字转换为HandleStream
socketConnection
,并在其上运行respondHTTP
和receiveHTTP
。 socketConnection
是一个奇怪的功能。前两个参数是主机名和运行服务器时不使用AFAICT的端口。
我使用了RecordWildCards
扩展名。它允许我在一个模式中编写Right (Request {..})
,并将记录的所有字段放在右侧。
答案 1 :(得分:5)
也许它希望您使用the accept
function from Network.Socket
代替Network
?这会为您提供Socket
而不是Handle
,您应该可以将其转换为receiveHTTP
可以使用的表单。
通常情况下,Handle
可以更好地直接使用,但是这里HTTP库正在为您处理它,所以它需要更低级别的接口。
编辑:在进一步查看后,似乎socketConnection
中的Network.TCP
功能可以满足您的需求。有趣的是,它实际上是在内部插入Handle
之前将其从内部读取,但似乎没有提供从外部提供的Handle
读取的方法。该函数的字符串参数应该是远程主机的名称,但它看起来只是保留供参考;它实际上并没有启动与该主机或任何东西的连接。