123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- #pragma once
- #include "httpagent.h"
- #include "httpparser.h"
- #include "http_digest.h"
- #include <util/system/compat.h>
- #include <util/string/vector.h>
- #include <util/network/ip.h>
- #include <library/cpp/uri/http_url.h>
- #include <library/cpp/http/misc/httpcodes.h>
- /********************************************************/
- // Section 1: socket handlers
- /********************************************************/
- // The following classes allows to adopt template scheme
- // THttpAgent for work with socket by flexible
- // object-style scheme.
- /********************************************************/
- // This class is used as a base one for flexible
- // socket handling
- class socketAbstractHandler {
- public:
- virtual bool Good() = 0;
- virtual int Connect(const TAddrList& addrs, TDuration Timeout) = 0;
- virtual void Disconnect() = 0;
- virtual void shutdown() = 0;
- virtual bool send(const char* message, ssize_t messlen) = 0;
- virtual bool peek() = 0;
- virtual ssize_t read(void* buffer, ssize_t buflen) = 0;
- virtual ~socketAbstractHandler() {
- }
- protected:
- socketAbstractHandler() {
- }
- };
- /********************************************************/
- // This class is used as a proxy between THttpAgent and
- // socketAbstractHandler
- // (it is used by template scheme,
- // so it does not have virtual methods)
- class TSocketHandlerPtr {
- protected:
- socketAbstractHandler* Handler_;
- public:
- TSocketHandlerPtr()
- : Handler_(nullptr)
- {
- }
- virtual ~TSocketHandlerPtr() {
- delete Handler_;
- }
- int Good() {
- return (Handler_ && Handler_->Good());
- }
- int Connect(const TAddrList& addrs, TDuration Timeout) {
- return (Handler_) ? Handler_->Connect(addrs, Timeout) : 1;
- }
- void Disconnect() {
- if (Handler_)
- Handler_->Disconnect();
- }
- void shutdown() {
- if (Handler_)
- Handler_->shutdown();
- }
- bool send(const char* message, ssize_t messlen) {
- return (Handler_) ? Handler_->send(message, messlen) : false;
- }
- virtual bool peek() {
- return (Handler_) ? Handler_->peek() : false;
- }
- virtual ssize_t read(void* buffer, ssize_t buflen) {
- return (Handler_) ? Handler_->read(buffer, buflen) : 0;
- }
- void setHandler(socketAbstractHandler* handler) {
- if (Handler_)
- delete Handler_;
- Handler_ = handler;
- }
- };
- /********************************************************/
- // Here is httpAgent that uses socketAbstractHandler class
- // ant its derivatives
- using httpSpecialAgent = THttpAgent<TSocketHandlerPtr>;
- /********************************************************/
- // Regular handler is used as implementation of
- // socketAbstractHandler for work through HTTP protocol
- class socketRegularHandler: public socketAbstractHandler {
- protected:
- TSimpleSocketHandler Socket_;
- public:
- socketRegularHandler()
- : Socket_()
- {
- }
- bool Good() override {
- return Socket_.Good();
- }
- int Connect(const TAddrList& addrs, TDuration Timeout) override {
- return Socket_.Connect(addrs, Timeout);
- }
- void Disconnect() override {
- Socket_.Disconnect();
- }
- void shutdown() override {
- //Do not block writing to socket
- //There are servers that works in a bad way with this
- //mSocket.shutdown();
- }
- bool send(const char* message, ssize_t messlen) override {
- return Socket_.send(message, messlen);
- }
- bool peek() override {
- return Socket_.peek();
- }
- ssize_t read(void* buffer, ssize_t buflen) override {
- return Socket_.read(buffer, buflen);
- }
- };
- /********************************************************/
- // The base factory that allows to choose an appropriate
- // socketAbstractHandler implementation by url schema
- class socketHandlerFactory {
- public:
- virtual ~socketHandlerFactory() {
- }
- //returns mHandler_HTTP for correct HTTP-based url
- virtual socketAbstractHandler* chooseHandler(const THttpURL& url);
- static socketHandlerFactory sInstance;
- };
- /********************************************************/
- // Section 2: the configurates tool to parse an HTTP-response
- /********************************************************/
- class httpAgentReader: public THttpParserGeneric<1> {
- protected:
- THttpAuthHeader Header_;
- httpSpecialAgent& Agent_;
- char* Buffer_;
- void* BufPtr_;
- int BufSize_;
- long BufRest_;
- void readBuf();
- bool step() {
- if (BufRest_ == 0)
- readBuf();
- if (eof())
- return false;
- return true;
- }
- public:
- httpAgentReader(httpSpecialAgent& agent,
- const char* baseUrl,
- bool assumeConnectionClosed,
- bool use_auth = false,
- int bufSize = 0x1000);
- ~httpAgentReader();
- bool eof() {
- return BufRest_ < 0;
- }
- int error() {
- return Header_.error;
- }
- void setError(int errCode) {
- Header_.error = errCode;
- }
- const THttpAuthHeader* getAuthHeader() {
- return &Header_;
- }
- const THttpHeader* readHeader();
- long readPortion(void*& buf);
- bool skipTheRest();
- };
- /********************************************************/
- // Section 3: the main class
- /********************************************************/
- class httpLoadAgent: public httpSpecialAgent {
- protected:
- socketHandlerFactory& Factory_;
- bool HandleAuthorization_;
- THttpURL URL_;
- bool PersistentConn_;
- httpAgentReader* Reader_;
- TVector<TString> Headers_;
- int ErrCode_;
- char* RealHost_;
- httpDigestHandler Digest_;
- void clearReader();
- bool doSetHost(const TAddrList& addrs);
- bool doStartRequest();
- public:
- httpLoadAgent(bool handleAuthorization = false,
- socketHandlerFactory& factory = socketHandlerFactory::sInstance);
- ~httpLoadAgent();
- void setRealHost(const char* host);
- void setIMS(const char* ifModifiedSince);
- void addHeaderInstruction(const char* instr);
- void dropHeaderInstructions();
- bool startRequest(const char* url,
- const char* url_to_merge = nullptr,
- bool persistent = false,
- const TAddrList& addrs = TAddrList());
- // deprecated v4-only
- bool startRequest(const char* url,
- const char* url_to_merge,
- bool persistent,
- ui32 ip);
- bool startRequest(const THttpURL& url,
- bool persistent = false,
- const TAddrList& addrs = TAddrList());
- bool setHost(const char* host_url,
- const TAddrList& addrs = TAddrList());
- bool startOneRequest(const char* local_url);
- const THttpAuthHeader* getAuthHeader() {
- if (Reader_ && Reader_->getAuthHeader()->use_auth)
- return Reader_->getAuthHeader();
- return nullptr;
- }
- const THttpHeader* getHeader() {
- if (Reader_)
- return Reader_->getAuthHeader();
- return nullptr;
- }
- const THttpURL& getURL() {
- return URL_;
- }
- bool eof() {
- if (Reader_)
- return Reader_->eof();
- return true;
- }
- int error() {
- if (ErrCode_)
- return ErrCode_;
- if (Reader_)
- return Reader_->error();
- return HTTP_BAD_URL;
- }
- long readPortion(void*& buf) {
- if (Reader_)
- return Reader_->readPortion(buf);
- return -1;
- }
- };
- /********************************************************/
|