Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ErrorClosed exception from Network.HTTP.simpleHTTP -- trying to upload images via XML-RPC with haxr

I'm trying to use haxr 3000.8.5 to upload images to a WordPress blog using the metaWeblog API---specifically, the newMediaObject method.

I've gotten it to work for small images, having successfully uploaded 20x20 icons in both PNG and JPG formats. However, when I try medium-sized images (say, 300x300) I get an ErrorClosed exception, presumably from the HTTP package (I did a bit of source diving, and found that haxr ultimately calls Network.HTTP.simpleHTTP).

Can anyone shed light on the reasons why a call to simpleHTTP might fail with ErrorClosed? Suggestions of things to try and potential workarounds are also welcome.

Here are links to full tcpdump output from a successful upload and from an unsuccessful upload.

The (sanitized) code is also shown below, in case it's of any use.

import           Network.XmlRpc.Client      (remote)
import           Network.XmlRpc.Internals   (Value(..), toValue)
import           Data.Char                  (toLower)
import           System.FilePath            (takeFileName, takeExtension)
import qualified Data.ByteString.Char8 as B
import           Data.Functor               ((<$>))

uploadMediaObject :: FilePath -> IO Value
uploadMediaObject file = do
  media <- mkMediaObject file
  remote "http://someblog.wordpress.com/xmlrpc.php" "metaWeblog.newMediaObject"
    "default" "username" "password" media

-- Create the required struct representing the image.
mkMediaObject :: FilePath -> IO Value
mkMediaObject filePath = do
  bits <- B.unpack <$> B.readFile filePath
  return $ ValueStruct
    [ ("name", toValue fileName)
    , ("type", toValue fileType)
    , ("bits", ValueBase64 bits)
    ]
  where
    fileName = takeFileName filePath
    fileType = case (map toLower . drop 1 . takeExtension) fileName of
                 "png"  -> "image/png"
                 "jpg"  -> "image/jpeg"
                 "jpeg" -> "image/jpeg"
                 "gif"  -> "image/gif"

main = do
  v <- uploadMediaObject "images/puppy.png"
  print v
like image 495
Brent Yorgey Avatar asked Jun 30 '12 21:06

Brent Yorgey


1 Answers

21:59:56.813021 IP 192.168.1.148.39571 > ..http: Flags [.]
22:00:01.922598 IP ..http > 192.168.1.148.39571: Flags [F.]

The connection is closed by the server after a 3-4 sec timeout as the client didn't send any data, to prevent slowloris and similar ddos attacks. (F is the FIN flag, to close one direction of the bidirectional connection).

The server does not wait for the client to close the connection (wait for eof/0 == recv(fd)) but uses the close() syscall; the kernel on the server will respond with [R]eset packets if it receives further data, as you can see at the end of your dump.

I guess the client first opens the http connection and then prepares the data which takes too long.

like image 135
Stefan Avatar answered Nov 03 '22 20:11

Stefan