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 20×20 icons in both PNG and JPG formats. However, when I try medium-sized images (say, 300×300) 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
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.