#pragma once #include #include #include #include #include #include #include #include #include #include #include #include "http.h" #include "http_proxy_ssl.h" namespace NHttp { struct TSocketDescriptor : NActors::TSharedDescriptor, THttpConfig { SocketType Socket; int GetDescriptor() override { return static_cast(Socket); } }; struct TEvHttpProxy { enum EEv { EvAddListeningPort = EventSpaceBegin(NActors::TEvents::ES_HTTP), EvConfirmListen, EvRegisterHandler, EvHttpIncomingRequest, EvHttpOutgoingRequest, EvHttpIncomingResponse, EvHttpOutgoingResponse, EvHttpConnectionOpened, EvHttpConnectionClosed, EvHttpAcceptorClosed, EvResolveHostRequest, EvResolveHostResponse, EvReportSensors, EvEnd }; static_assert(EvEnd < EventSpaceEnd(NActors::TEvents::ES_HTTP), "ES_HTTP event space is too small."); struct TEvAddListeningPort : NActors::TEventLocal { TIpPort Port; TString WorkerName; bool Secure = false; TString CertificateFile; TString PrivateKeyFile; TString SslCertificatePem; TEvAddListeningPort(TIpPort port) : Port(port) {} TEvAddListeningPort(TIpPort port, const TString& workerName) : Port(port) , WorkerName(workerName) {} }; struct TEvConfirmListen : NActors::TEventLocal { THttpConfig::SocketAddressType Address; TEvConfirmListen(const THttpConfig::SocketAddressType& address) : Address(address) {} }; struct TEvRegisterHandler : NActors::TEventLocal { TString Path; TActorId Handler; TEvRegisterHandler(const TString& path, const TActorId& handler) : Path(path) , Handler(handler) {} }; struct TEvHttpIncomingRequest : NActors::TEventLocal { THttpIncomingRequestPtr Request; TEvHttpIncomingRequest(THttpIncomingRequestPtr request) : Request(std::move(request)) {} }; struct TEvHttpOutgoingRequest : NActors::TEventLocal { THttpOutgoingRequestPtr Request; TDuration Timeout; TEvHttpOutgoingRequest(THttpOutgoingRequestPtr request) : Request(std::move(request)) {} TEvHttpOutgoingRequest(THttpOutgoingRequestPtr request, TDuration timeout) : Request(std::move(request)) , Timeout(timeout) {} }; struct TEvHttpIncomingResponse : NActors::TEventLocal { THttpOutgoingRequestPtr Request; THttpIncomingResponsePtr Response; TString Error; TEvHttpIncomingResponse(THttpOutgoingRequestPtr request, THttpIncomingResponsePtr response, const TString& error) : Request(std::move(request)) , Response(std::move(response)) , Error(error) {} TEvHttpIncomingResponse(THttpOutgoingRequestPtr request, THttpIncomingResponsePtr response) : Request(std::move(request)) , Response(std::move(response)) {} TString GetError() const { TStringBuilder error; if (Response != nullptr && !Response->Status.StartsWith('2')) { error << Response->Status << ' ' << Response->Message; } if (!Error.empty()) { if (!error.empty()) { error << ';'; } error << Error; } return error; } }; struct TEvHttpOutgoingResponse : NActors::TEventLocal { THttpOutgoingResponsePtr Response; TEvHttpOutgoingResponse(THttpOutgoingResponsePtr response) : Response(std::move(response)) {} }; struct TEvHttpConnectionOpened : NActors::TEventLocal { TString PeerAddress; TActorId ConnectionID; TEvHttpConnectionOpened(const TString& peerAddress, const TActorId& connectionID) : PeerAddress(peerAddress) , ConnectionID(connectionID) {} }; struct TEvHttpConnectionClosed : NActors::TEventLocal { TActorId ConnectionID; TDeque RecycledRequests; TEvHttpConnectionClosed(const TActorId& connectionID) : ConnectionID(connectionID) {} TEvHttpConnectionClosed(const TActorId& connectionID, TDeque recycledRequests) : ConnectionID(connectionID) , RecycledRequests(std::move(recycledRequests)) {} }; struct TEvHttpAcceptorClosed : NActors::TEventLocal { TActorId ConnectionID; TEvHttpAcceptorClosed(const TActorId& connectionID) : ConnectionID(connectionID) {} }; struct TEvResolveHostRequest : NActors::TEventLocal { TString Host; TEvResolveHostRequest(const TString& host) : Host(host) {} }; struct TEvResolveHostResponse : NActors::TEventLocal { TString Host; TSockAddrInet6 Address; TString Error; TEvResolveHostResponse(const TString& host, const TSockAddrInet6& address) : Host(host) , Address(address) {} TEvResolveHostResponse(const TString& error) : Error(error) {} }; struct TEvReportSensors : NActors::TEventLocal { TString Direction; TString Host; TString Url; TString Status; TDuration Time; TEvReportSensors( TStringBuf direction, TStringBuf host, TStringBuf url, TStringBuf status, TDuration time) : Direction(direction) , Host(host) , Url(url) , Status(status) , Time(time) {} }; }; struct TEndpointInfo { TActorId Proxy; TActorId Owner; TString WorkerName; bool Secure; TSslHelpers::TSslHolder SecureContext; }; NActors::IActor* CreateHttpProxy(std::weak_ptr registry = NMonitoring::TMetricRegistry::SharedInstance()); NActors::IActor* CreateHttpAcceptorActor(const TActorId& owner, const TActorId& poller); NActors::IActor* CreateOutgoingConnectionActor(const TActorId& owner, const TString& host, bool secure, const TActorId& poller); NActors::IActor* CreateIncomingConnectionActor( const TEndpointInfo& endpoint, TIntrusivePtr socket, THttpConfig::SocketAddressType address, THttpIncomingRequestPtr recycledRequest = nullptr); TEvHttpProxy::TEvReportSensors* BuildOutgoingRequestSensors(const THttpOutgoingRequestPtr& request, const THttpIncomingResponsePtr& response); TEvHttpProxy::TEvReportSensors* BuildIncomingRequestSensors(const THttpIncomingRequestPtr& request, const THttpOutgoingResponsePtr& response); }