[Haskell-cafe] Re: Strange HTTP module behavior [PATCH]

John Goerzen jgoerzen at complete.org
Fri Feb 18 16:44:19 EST 2005


On 2005-02-18, John Goerzen <jgoerzen at complete.org> wrote:
> First, even though I am sending an accurate Content-Length header with
> my POST message, the server is timing out and returning a 500 Internal
> Server Error document.

Looks like that was a server bug.

> Second, after reading that error document, Network.HTTP is generating an
> error of its own.  Here's an strace illustrating it:

This one was a bug in HTTP.  Actually, I am stunned that nobody found it
before, because it looks to me that it would cause an exception to be
raised on every single HTTP hit.

It turns out that Network.Socket.recv raises an EOF error when it gets
back 0 bytes of data.  HTTP is expecting it to return an empty list for
some reason.

The below patch fixed it for me.

--- orig/http/Network/HTTP.hs
+++ mod/http/Network/HTTP.hs
@@ -147,6 +147,7 @@
 import Text.ParserCombinators.ReadP
 import Text.Read.Lex 
 import System.IO
+import qualified System.IO.Error
 
 import Foreign.C.Error
 
@@ -651,7 +652,7 @@
 instance Stream Socket where
     readBlock sk n = (liftM Right $ fn n) `Exception.catch` (handleSocketError sk)
         where
-            fn x = do { str <- recv sk x
+            fn x = do { str <- myrecv sk x
                       ; let len = length str
                       ; if len < x
                           then ( fn (x-len) >>= \more -> return (str++more) )                        
@@ -665,7 +666,7 @@
     readLine sk = (liftM Right $ fn "") `Exception.catch` (handleSocketError sk)
             where
                 fn str =
-                    do { c <- recv sk 1 -- like eating through a straw.
+                    do { c <- myrecv sk 1 -- like eating through a straw.
                        ; if null c || c == "\n"
                            then return (reverse str++c)
                            else fn (head c:str)
@@ -706,7 +707,7 @@
              ConnClosed -> return (Left ErrorClosed)
              (MkConn sk addr bfr _)
                  | null bfr ->  {- read in buffer -}
-                      do { str <- recv sk 1000  -- DON'T use "readBlock sk 1000" !!
+                      do { str <- myrecv sk 1000  -- DON'T use "readBlock sk 1000" !!
                                                 -- ... since that call will loop.
                          ; let len = length str
                          ; if len == 0   {- indicates a closed connection -}
@@ -1274,3 +1275,7 @@
 urlEncodeVars [] = []
 
 
+myrecv :: Socket -> Int -> IO String
+myrecv sock len =
+    let handler e = if isEOFError e then return [] else ioError e
+        in System.IO.catch (recv sock len) handler
\ No newline at end of file






More information about the Haskell-Cafe mailing list