Ejemplo n.º 1
0
    std::shared_ptr<Response> request_read() {
      std::shared_ptr<Response> response(new Response());

      try {
        size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");

        size_t num_additional_bytes = response->content_buffer.size() - bytes_transferred;

        parse_response_header(response, response->content);

        auto header_it = response->header.find("Content-Length");
        if (header_it != response->header.end()) {
          auto content_length = stoull(header_it->second);
          if (content_length>num_additional_bytes) {
            boost::asio::read(*socket, response->content_buffer,
              boost::asio::transfer_exactly(content_length - num_additional_bytes));
          }
        }
        else if ((header_it = response->header.find("Transfer-Encoding")) != response->header.end() && header_it->second == "chunked") {
          boost::asio::streambuf streambuf;
          std::ostream content(&streambuf);

          std::streamsize length;
          std::string buffer;
          do {
            size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
            std::string line;
            getline(response->content, line);
            bytes_transferred -= line.size() + 1;
            line.pop_back();
            length = stol(line, 0, 16);

            auto num_additional_bytes = static_cast<std::streamsize>(response->content_buffer.size() - bytes_transferred);

            if ((2 + length)>num_additional_bytes) {
              boost::asio::read(*socket, response->content_buffer,
                boost::asio::transfer_exactly(2 + length - num_additional_bytes));
            }

            buffer.resize(static_cast<size_t>(length));
            response->content.read(&buffer[0], length);
            content.write(&buffer[0], length);

            //Remove "\r\n"
            response->content.get();
            response->content.get();
          } while (length>0);

          std::ostream response_content_output_stream(&response->content_buffer);
          response_content_output_stream << content.rdbuf();
        }
      }
      catch (const std::exception& e) {
        socket_error = true;
        throw std::invalid_argument(e.what());
      }

      return response;
    }
Ejemplo n.º 2
0
        std::shared_ptr<Response> request(const std::string& request_type, const std::string& path, std::ostream& content, 
                const std::map<std::string, std::string>& header=std::map<std::string, std::string>()) {
            std::string corrected_path=path;
            if(corrected_path=="")
                corrected_path="/";
            
            content.seekp(0, std::ios::end);
            size_t content_length=content.tellp();
            content.seekp(0, std::ios::beg);
            
            boost::asio::streambuf write_buffer;
            std::ostream write_stream(&write_buffer);
            write_stream << request_type << " " << corrected_path << " HTTP/1.1\r\n";
            write_stream << "Host: " << host << "\r\n";
            for(auto& h: header) {
                write_stream << h.first << ": " << h.second << "\r\n";
            }
            if(content_length>0)
                write_stream << "Content-Length: " << std::to_string(content_length) << "\r\n";
            write_stream << "\r\n";
            if(content_length>0)
                write_stream << content.rdbuf();
            
            std::shared_ptr<Response> response(new Response());
            
            try {
                connect();
                              
                boost::asio::write(*socket, write_buffer);
                
                size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n\r\n");
                
                size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
                
                parse_response_header(response, response->content);
                                
                if(response->header.count("Content-Length")>0) {
                    boost::asio::read(*socket, response->content_buffer, 
                            boost::asio::transfer_exactly(stoull(response->header["Content-Length"])-num_additional_bytes));
                }
                else if(response->header.count("Transfer-Encoding")>0 && response->header["Transfer-Encoding"]=="chunked") {
                    boost::asio::streambuf streambuf;
                    std::ostream content(&streambuf);
                    
                    size_t length;
                    std::string buffer;
                    do {
                        size_t bytes_transferred = boost::asio::read_until(*socket, response->content_buffer, "\r\n");
                        std::string line;
                        getline(response->content, line);
                        bytes_transferred-=line.size()+1;
                        line.pop_back();
                        length=stoull(line, 0, 16);

                        size_t num_additional_bytes=response->content_buffer.size()-bytes_transferred;
                    
                        if((2+length)>num_additional_bytes) {
                            boost::asio::read(*socket, response->content_buffer, 
                                boost::asio::transfer_exactly(2+length-num_additional_bytes));
                        }
                                                
                        buffer.resize(length);
                        response->content.read(&buffer[0], length);
                        content.write(&buffer[0], length);

                        //Remove "\r\n"
                        response->content.get();
                        response->content.get();
                    } while(length>0);
                    
                    std::ostream response_content_output_stream(&response->content_buffer);
                    response_content_output_stream << content.rdbuf();
                }
            }
            catch(const std::exception& e) {
                socket_error=true;
                throw std::invalid_argument(e.what());
            }
            
            return response;
        }