From 306b77bfc51510072fc7900dc7229f7726c9d589 Mon Sep 17 00:00:00 2001 From: Mario Liebisch Date: Tue, 11 Dec 2012 19:08:56 +0100 Subject: [PATCH] Added support for chunked http transfers sf::Http now understands transfers that are sent using Chunked Transfer Encoding (RFC 2616; section 3.6.1). --- include/SFML/Network/Http.hpp | 12 +++++++++ src/SFML/Network/Http.cpp | 46 +++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/include/SFML/Network/Http.hpp b/include/SFML/Network/Http.hpp index 7338f5ab..04e8da31 100644 --- a/include/SFML/Network/Http.hpp +++ b/include/SFML/Network/Http.hpp @@ -316,6 +316,18 @@ public : //////////////////////////////////////////////////////////// void parse(const std::string& data); + + //////////////////////////////////////////////////////////// + /// \brief Read values passed in the answer header + /// + /// This function is used by Http to extract values passed + /// in the response. + /// + /// \param in String stream containing the header values + /// + //////////////////////////////////////////////////////////// + void parseFields(std::istream &in); + //////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////// diff --git a/src/SFML/Network/Http.cpp b/src/SFML/Network/Http.cpp index 0381341b..87ef9cfe 100644 --- a/src/SFML/Network/Http.cpp +++ b/src/SFML/Network/Http.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace @@ -231,9 +232,48 @@ void Http::Response::parse(const std::string& data) } // Ignore the end of the first line - in.ignore(10000, '\n'); + in.ignore(std::numeric_limits::max(), '\n'); // Parse the other lines, which contain fields, one by one + parseFields(in); + + m_body.clear(); + + // Determine whether the transfer is chunked + if (toLower(getField("transfer-encoding")) != "chunked") + { + // Not chunked - just read everything at once + std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(m_body)); + } + else + { + // Chunked - have to read chunk by chunk + std::size_t length; + + // Read all chunks, identified by a chunk-size not being 0 + while (in >> std::hex >> length) + { + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Copy the actual content data + std::istreambuf_iterator it(in); + for (std::size_t i = 0; i < length; i++) + m_body.push_back(*it++); + } + + // Drop the rest of the line (chunk-extension) + in.ignore(std::numeric_limits::max(), '\n'); + + // Read all trailers (if present) + parseFields(in); + } +} + + +//////////////////////////////////////////////////////////// +void Http::Response::parseFields(std::istream &in) +{ std::string line; while (std::getline(in, line) && (line.size() > 2)) { @@ -252,10 +292,6 @@ void Http::Response::parse(const std::string& data) m_fields[toLower(field)] = value; } } - - // Finally extract the body - m_body.clear(); - std::copy(std::istreambuf_iterator(in), std::istreambuf_iterator(), std::back_inserter(m_body)); }