2012-06-30 7 views
7

Estoy tratando de usar haxr 3000.8.5 para subir imágenes a un blog WordPress usando la API metaWeblog --- específicamente, el newMediaObject método.ErrorExcepción cerrada de Network.HTTP.simpleHTTP - tratando de cargar imágenes a través de XML-RPC con haxr

Lo he conseguido para imágenes pequeñas, habiendo cargado con éxito iconos 20x20 en formatos PNG y JPG. Sin embargo, cuando intento imágenes de tamaño mediano (por ejemplo, 300x300) obtengo una excepción de ErrorClosed, presumiblemente del paquete HTTP (hice un poco de buceo en la fuente, y encontré que haxr finalmente llama al Network.HTTP.simpleHTTP).

¿Alguien puede arrojar luz sobre las razones por las que una llamada a simpleHTTP puede fallar con ErrorClosed? Sugerencias de cosas para probar y posibles soluciones alternativas también son bienvenidas.

Aquí están los enlaces a full tcpdump output from a successful upload y from an unsuccessful upload.

El código (desinfectado) también se muestra a continuación, en caso de que sea de alguna utilidad.

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 
+1

¿Ha intentado utilizar tcpdump o wireshark para inspeccionar la sesión HTTP? –

+0

Gracias por la sugerencia. Realmente sé muy poco sobre redes, especialmente cuando se trata de depuración. He agregado algunos resultados de tcpdump a la pregunta. –

+0

@BrentYorgey: Creo que querrás editar ese resultado en tu pregunta. Es mucho más fácil leerlo formateado adecuadamente allí, incluso si se adapta al espacio limitado que recibe en un comentario. –

Respuesta

4
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.] 

la conexión se cierra por el servidor después de un tiempo de espera de 3-4 segundos y cuando el cliente no ha enviado ningún dato, para prevenir los ataques DDoS slowloris y similares. (F es el indicador FIN, para cerrar una dirección de la conexión bidireccional).

El servidor no espera que el cliente cierre la conexión (espere eof/0 == recv (fd)) pero utiliza la llamada a sistema close(); el kernel en el servidor responderá con paquetes [R] eset si recibe más datos, como puede ver al final de su volcado.

Supongo que el cliente primero abre la conexión http y luego prepara los datos, lo que lleva demasiado tiempo.

+0

¡Gracias, esto es exactamente lo que necesitaba saber! Resulta que la pereza de Haskell me estaba mordiendo a lo grande. La solución no es trivial (requiere parchear Haxr) pero he conseguido que funcione ahora. –

Cuestiones relacionadas