HTTP Client mit Boost ASIO in einem Proxy Netzwerk



  • Hallo Leute,

    ich habe mir mit Boost (ASIO) einen HTTPClient gebaut.

    Es treten jetzt bei einem speziellen Fall folgende Probleme auf:

    Die Methode handleReadContent() empfängt die Daten, und schreibt sie in ein File. Das passiert so lange, bis eof (end of file) erreicht ist.
    Es kann jetzt aber passieren, dass kein eof kommt (keine Daten kommen). Das File ist aber trotzdem komplett geladen nur leider steht mein C++ Programm.
    Schliesslich wurde die eof Bedienung nie erfüllt.

    Wann passiert das ganze:
    - Nur bei großen Files (jpg funktioniert trotzdem, Videos funktionieren nicht)
    - Nur bei einem speziellen Netzwerk (ich glaube es hat was mit Proxy zu tun)

    HTTP-Response von dem Netzwerk mit Proxy (funktioniert nicht):

    Via: 1.1 STATMG01
    Connection: Keep-Alive
    Proxy-Connection: Keep-Alive
    Content-Length: 11713528
    Date: Thu, 11 Apr 2013 11:24:
    Content-Type: text/texmacs
    ETag: "788a9e9-b2bbf8-4d446d6
    Server: Apache/2.2.16 (Debian
    Accept-Ranges: bytes
    Last-Modified: Sun, 27 Jan 20
    

    HTTP-Response von funktionierenden Netzwerk:

    Connection: close
    Content-Length: 11713528
    Date: Thu, 11 Apr 2013 11:23:50 GMT
    Content-Type: text/texmacs
    ETag: "788a9e9-b2bbf8-4d446d6991b00"
    Server: Apache/2.2.16 (Debian)
    Accept-Ranges: bytes
    Last-Modified: Sun, 27 Jan 2013 15:30:20 GMT
    

    Unterschiede der HTTP-Headers:

    - Connection ist Keep-alive sonst close
    - Proxy-Connection: Keep-Alive
    - Via: 1.1 STATMG01 wurde hinzugefügt

    Also ich nehme mal an der Proxy schreibt da böses Header-Zeugs in meinen Response-Header. Boost kann damit nicht umgehen..? Oder wie kann man sich das sonst vorstellen?

    Es folgt nun die Methode wo alles zum stehen kommt.

    void HTTPClient::handleReadContent(const boost::system::error_code& error, size_t bytesTransferred)
    {
        if (!error)
        {
            m_fileStream.open(m_filename.c_str(), std::fstream::out | std::fstream::app);
    
            m_fileStream << &m_Response;
    
            m_fileStream.close();
    
            // Continue reading remaining data until EOF.
            boost::asio::async_read(*m_Socket, m_Response,
            boost::asio::transfer_at_least(1),
            boost::bind(&HTTPClient::handleReadContent, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        }
        else if (error != boost::asio::error::eof)
        {
          std::cout << "error in handleReadContent() " << error << "\n";
        }
        else if(error == boost::asio::error::eof)
        {
    
            m_fileStream.open(m_filename.c_str(), std::fstream::out | std::fstream::app);
            m_fileStream << &m_Response;
            m_fileStream.close();
        }
    }
    

    Hier noch der Code wie mein HTTP-Header zusammen gebaut wird. Vielleicht mache ich da ja auch schon was falsch.

    std::ostream requestStream(&m_Request);
    requestStream << "GET " << "/" << m_URL.getPath()+m_URL.getFile() << " HTTP/1.0\r\n";
    requestStream << "Host: " << m_URL.getHost() << "\r\n";
    requestStream << "Accept: */*\r\n";
    addHeaderFieldsToHeader(requestStream);
    requestStream << "Connection: close\r\n\r\n";
    

    Wäre echt super wenn mir da jemand ein paar Tipps geben könnte. Ich weiß da nicht mehr weiter. Vielleicht gibt es einfache Workarounds?

    thx und lg
    Darian



  • Du musst erst den Response-Header empfangen, dann Connection und Content-Length auswerten und dann entsprechend den Response-Body empfangen.

    D.h. wenn Connection: Keep-Alive gesetzt ist, musst du auch Content-Length auswerten und dann noch genau soviele Bytes empfangen, wie angegeben ist.

    Danach kannst du die Connection entweder schliessen (ein wenig verschwenderisch) oder wieder für den nächsten Request benutzen.

    http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html



  • Okay danke, werde mir das mal genauer ansehen.

    Weil bis jetzt hatte ich immer HTTP 1.0 verwendet und Connection:Close. Mein HTTPClient kann also mit den keep-alive noch nicht umgehen.

    thx und lg
    Darian


Log in to reply