| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | 
#pragma once#include <stddef.h>     // for size_t#include <cstdint>      // for uint8_t, int32_t#include <memory>       // for make_unique, unique_ptr#include <string>       // for string#include <string_view>  // for string_view#include <utility>      // for pair#include <vector>       // for vector#include "SocketStream.h"  // for SocketStream#include "URLParser.h"     // for URLParser#ifndef BELL_DISABLE_FMT#include "fmt/core.h"  // for format#endif#include "picohttpparser.h"  // for phr_headernamespace bell {class HTTPClient { public:  // most basic header type, represents by a key-val  typedef std::pair<std::string, std::string> ValueHeader;  typedef std::vector<ValueHeader> Headers;  // Helper over ValueHeader, formatting a HTTP bytes range  struct RangeHeader {    static ValueHeader range(int32_t from, int32_t to) {#ifndef BELL_DISABLE_FMT      return ValueHeader{"Range", fmt::format("bytes={}-{}", from, to)};#else      return ValueHeader{          "Range", "bytes=" + std::to_string(from) + "-" + std::to_string(to)};#endif    }    static ValueHeader last(int32_t nbytes) {#ifndef BELL_DISABLE_FMT      return ValueHeader{"Range", fmt::format("bytes=-{}", nbytes)};#else      return ValueHeader{"Range", "bytes=-" + std::to_string(nbytes)};#endif    }  };  class Response {   public:    Response(){};    ~Response();    /**    * Initializes a connection with a given url.    */    void connect(const std::string& url);    void rawRequest(const std::string& method, const std::string& url,                    const std::vector<uint8_t>& content, Headers& headers);    void get(const std::string& url, Headers headers = {});    void post(const std::string& url, Headers headers = {},              const std::vector<uint8_t>& body = {});    std::string_view body();    std::vector<uint8_t> bytes();    std::string_view header(const std::string& headerName);    bell::SocketStream& stream() { return this->socketStream; }    size_t contentLength();    size_t totalLength();   private:    bell::URLParser urlParser;    bell::SocketStream socketStream;    struct phr_header phResponseHeaders[32];    const size_t HTTP_BUF_SIZE = 1024;    std::vector<uint8_t> httpBuffer = std::vector<uint8_t>(HTTP_BUF_SIZE);    std::vector<uint8_t> rawBody = std::vector<uint8_t>();    size_t httpBufferAvailable;    size_t contentSize = 0;    bool hasContentSize = false;    Headers responseHeaders;    void readResponseHeaders();    void readRawBody();  };  enum class Method : uint8_t { GET = 0, POST = 1 };  struct Request {    std::string url;    Method method;    Headers headers;  };  static std::unique_ptr<Response> get(const std::string& url,                                       Headers headers = {}) {    auto response = std::make_unique<Response>();    response->connect(url);    response->get(url, headers);    return response;  }  static std::unique_ptr<Response> post(const std::string& url,                                        Headers headers = {},                                        const std::vector<uint8_t>& body = {}) {    auto response = std::make_unique<Response>();    response->connect(url);    response->post(url, headers, body);    return response;  }};}  // namespace bell
 |