Advertisement
Guest User

Untitled

a guest
Dec 29th, 2018
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.72 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include "../auto-ptr.h"
  4. #include "../byte-array.h"
  5. #include "../object.h"
  6. #include "../promise.h"
  7.  
  8. #include "common-http.h"
  9. #include "message.h"
  10.  
  11. namespace fn {
  12.     namespace crypto {
  13.         class TLSStream;
  14.     }
  15. } // namespace fn
  16.  
  17. namespace fn {
  18. FN_UNINDENT
  19.  
  20. namespace http {
  21.  
  22.     class ProxyStateFactory;
  23.  
  24.     class FN_EXPORT ClientSession : public RefCountedObject
  25.     {
  26.     public:
  27.         using AuthorizationCallback =
  28.             Function<Optional<Promise<http::Request>>(const http::Request & request, const http::Response &)>;
  29.  
  30.         using RedirectCallback = Function<bool(http::Request & newRequest, int count)>;
  31.  
  32.         class Request : public RefCountedObject
  33.         {
  34.         public:
  35.             // can be modified until sent(), after that modifications will be ignored
  36.             virtual http::Request & request() = 0;
  37.             virtual const http::Request & request() const = 0;
  38.  
  39.             // available after onResponseReceived callback is invoked
  40.             virtual const Optional<http::Response> & response() const = 0;
  41.  
  42.             // Must be set before send()
  43.             virtual void setChunked(bool chunked) = 0;
  44.  
  45.             // Must be set before send()
  46.             virtual void setBody(ByteArray body) = 0;
  47.  
  48.             // Returns true if the underlying stream is in encrypted state
  49.             virtual bool secure() const = 0;
  50.  
  51.             // May be called after promise returned from send() is fulfilled
  52.             //
  53.             // With chunked transfer every call will result in one chunk being sent; Send
  54.             // empty buffer to finish request (last chunk).
  55.             //
  56.             virtual Promise<void> appendBody(const UInt8 * data, SizeType size) = 0;
  57.  
  58.             virtual Promise<void> appendBody(ByteArray buffer) = 0;
  59.  
  60.             // Allows postprocessing / intercepting redirect; You can inspect or modify
  61.             // new request from the callback. Request will contain new (redirect) URL
  62.             // Returning false from callback will abort the redirect and process the
  63.             // response regularly
  64.             virtual void onRedirect(RedirectCallback cb) = 0;
  65.  
  66.             // Called during authorization request; Callback can return Promise for new
  67.             // authenticated request or NullOptional to finish current response
  68.             virtual void onAuthorizationRequired(AuthorizationCallback cb) = 0;
  69.  
  70.             // If upgrade callback is set, it will be invoked during upgrade response; In
  71.             // this case, none of the onResponseReceived, onResponseData and
  72.             // onResponseDone callbacks will be called. Callback must take ownership of
  73.             // the stream and can use it for new protocol. The stream will have reading
  74.             // stopped just after the headers
  75.             // As special case, onUpgrade is also called during CONNECT requests when
  76.             // response is 200 (OK)
  77.             virtual void onUpgrade(Function<void(ap_<uv::Stream>)> cb) = 0;
  78.  
  79.             // Received when response headers are received, before data
  80.             virtual void onResponseReceived(Function<void()> cb) = 0;
  81.  
  82.             // Called possibly repeatedly for response data
  83.             virtual void onResponseData(Function<void(const UInt8 *, SizeType)> cb) = 0;
  84.  
  85.             // Called when response is finished;
  86.             virtual void onResponseDone(Function<void()> cb) = 0;
  87.  
  88.             // Called on connection error; This means system error, not HTTP error status
  89.             virtual void onConnectionError(Function<void(std::exception_ptr e)> cb) = 0;
  90.  
  91.             // Sends the request; Any modifications to request past this point may be
  92.             // ignored
  93.             virtual Promise<void> send() = 0;
  94.  
  95.             // Convenience method that sends the request and gathers entire response
  96.             virtual Promise<ByteArray> sendAndReceive() = 0;
  97.  
  98.             // Cancels the request. Connection will be closed, callbacks will be removed.
  99.             virtual void cancel() = 0;
  100.         };
  101.  
  102.         //
  103.         //
  104.         //
  105.  
  106.         // Creates new ClientSession instance using system proxy factory
  107.         static ap<ClientSession> create(ap_<crypto::TLSContext> TLSContext);
  108.  
  109.         static ap<ClientSession> create(ap_<ProxyStateFactory> factory);
  110.  
  111.         //
  112.         //
  113.         //
  114.  
  115.         // Creates HTTP Request instance
  116.         virtual ap<Request> createRequest(const String & method,
  117.                                           const URL & url) = 0; // must be absolute
  118.  
  119.         // request URL must be absolute
  120.         virtual ap<Request> createRequest(const http::Request & request) = 0;
  121.  
  122.         //
  123.         // Settings, changing these will not affect existing or pooled connections
  124.         //
  125.  
  126.         // If connection can not be established within the timeout request will fail with
  127.         // TimedOutException
  128.         void setConnectionTimeout(const Duration & timeout) { _connectionTimeout = timeout; }
  129.         const Duration & connectionTimeout() const { return _connectionTimeout; }
  130.  
  131.         // TCP options
  132.  
  133.         void setNoDelay(bool noDelay) { _noDelay = noDelay; }
  134.         bool noDelay() const { return _noDelay; }
  135.  
  136.         void setTCPKeepAlive(bool keepAlive) { _keepAlive = keepAlive; }
  137.         bool tcpKeepAlive() const { return _keepAlive; }
  138.  
  139.         void setTCPKeepAliveTimeout(const Duration & timeout) { _tcpKeepAliveTimeout = timeout; }
  140.         const Duration & tcpKeepAliveTimeout() const { return _tcpKeepAliveTimeout; }
  141.  
  142.         // HTTP options
  143.  
  144.         void setHTTPKeepAliveTimeout(const Duration & timeout) { _httpKeepAliveTimeout = timeout; }
  145.         const Duration & httpKeepAliveTimeout() const { return _httpKeepAliveTimeout; }
  146.  
  147.         // Per session authorization callback; Can be overriden on individual requests
  148.         void onAuthorizationRequired(AuthorizationCallback cb) { _onAuthorizationRequired = FN_MOVE(cb); }
  149.  
  150.         // Per session redirect callback; Can be overriden on individual requests
  151.         void onRedirect(RedirectCallback cb) { _onRedirect = FN_MOVE(cb); }
  152.  
  153.     private:
  154.         Duration _connectionTimeout = Duration::withSeconds(30);
  155.         bool _noDelay = true;
  156.         bool _keepAlive = true;
  157.         Duration _tcpKeepAliveTimeout = Duration::withSeconds(60);
  158.         Duration _httpKeepAliveTimeout = Duration::withSeconds(60);
  159.  
  160.     protected:
  161.         AuthorizationCallback _onAuthorizationRequired;
  162.         RedirectCallback _onRedirect;
  163.     };
  164.  
  165.     //
  166.     // Represents proxy state for individual connection; Responsible for
  167.     // creating TLS stream and processing individual requests
  168.     //
  169.     class FN_EXPORT ProxyState : public RefCountedObject
  170.     {
  171.     public:
  172.         virtual Promise<ap<crypto::TLSStream>> createStream(const http::Request & request) = 0;
  173.  
  174.         virtual void processRequest(http::Request & request) = 0;
  175.     };
  176.  
  177.     //
  178.     // Creates proxy state for individual requests
  179.     //
  180.     class FN_EXPORT ProxyStateFactory : public RefCountedObject
  181.     {
  182.     public:
  183.         virtual Promise<ap<ProxyState>> createProxyState(const http::Request & request) = 0;
  184.     };
  185.  
  186.     //
  187.     // Proxy state that creates direct connection (not proxied)
  188.     //
  189.     class FN_EXPORT PassthroughProxyState : public ProxyState
  190.     {
  191.     public:
  192.         PassthroughProxyState(ap_<crypto::TLSContext> context);
  193.         ~PassthroughProxyState() override;
  194.  
  195.         Promise<ap<crypto::TLSStream>> createStream(const http::Request & request) override;
  196.  
  197.         void processRequest(http::Request & request) override;
  198.  
  199.     private:
  200.         ap<crypto::TLSContext> _context;
  201.     };
  202.  
  203.     //
  204.     // For every request creates PassthroughProxyState
  205.     //
  206.     class FN_EXPORT PassthroughProxyStateFactory : public ProxyStateFactory
  207.     {
  208.     public:
  209.         PassthroughProxyStateFactory(ap_<crypto::TLSContext> context);
  210.  
  211.         Promise<ap<ProxyState>> createProxyState(const http::Request & request) override;
  212.  
  213.     protected:
  214.         ~PassthroughProxyStateFactory() override;
  215.  
  216.     private:
  217.         ap<crypto::TLSContext> _context;
  218.     };
  219.  
  220.     // Lowlevel API for single HTTP stream
  221.     class FN_EXPORT SimpleClientSession : public RefCountedObject, private ResponseParserDelegate
  222.     {
  223.     public:
  224.         class Delegate
  225.         {
  226.         public:
  227.             enum class ResponseResult // must match values from parser
  228.             {
  229.                 CONTINUE = 0,
  230.                 FORCE_NO_BODY = 1,
  231.                 FORCE_UPGRADE = 2
  232.             };
  233.  
  234.             // Invoked when server can accept client body; it is possible for this
  235.             // callback to be invoked from within sendRequest()
  236.             virtual void onCanSendBody() = 0;
  237.  
  238.             // Invoked when response headers are available
  239.             virtual ResponseResult onResponseHeaders(Response && response, bool keepAlive, bool upgrade) = 0;
  240.  
  241.             // Periodically invoked on response data
  242.             virtual void onResponseData(const UInt8 * data, SizeType size) = 0;
  243.  
  244.             // Possibly invoked on additional final headers after chunked response
  245.             virtual void onAdditionalResponseHeader(const String & name, const String & value) = 0;
  246.  
  247.             // Invoked when respone is finished
  248.             virtual void onResponseDone() = 0;
  249.  
  250.             // Invoked on parsing / connection errro (not on HTTP error code);
  251.             // After this the connection and client session should be discarded
  252.             virtual void onError(std::exception_ptr error) = 0;
  253.  
  254.             virtual ~Delegate() = default;
  255.         };
  256.  
  257.         // Sends the request
  258.         // It is not permitted to call this while another request is in progress, or the
  259.         // request has been cancelled, or after error
  260.         void sendRequest(const Request & request);
  261.  
  262.         // Can only be called after onCanSendBody callback; Callback will be invoked after
  263.         // successful write; Callback will not be invoked after request was cancelled or
  264.         // after error
  265.         void appendRequestBody(const UInt8 * data, SizeType size, Function<void()> done = nullptr);
  266.  
  267.         // Can only be called after onCanSendBody callback; Callback will be invoked after
  268.         // successful write; Callback will not be invoked after request was cancelled or
  269.         // after error
  270.         void appendRequestBody(ByteArray buffer, Function<void()> done = nullptr);
  271.  
  272.         // reading will be stopped and no callbacks will be invoked; It is not possible to
  273.         // reuse cancelled client session
  274.         void cancel();
  275.  
  276.         // constructor
  277.         SimpleClientSession(ap_<uv::Stream> stream, Delegate & delegate);
  278.  
  279.         //
  280.         ~SimpleClientSession() override;
  281.  
  282.     private:
  283.         OnMessageResult onMessageHeader(Response && message, bool keepAlive, bool upgrade) override;
  284.         void onMessageData(const UInt8 * data, SizeType size) override;
  285.         void onMessageAdditionalHeader(const String & name, const String & value) override;
  286.         void onMessageDone(bool & stopParsing) override;
  287.         void onError(std::exception_ptr error) override;
  288.  
  289.         void write(const UInt8 * data, SizeType size, Function<void()> done = nullptr);
  290.         void write(ByteArray, Function<void()> done = nullptr);
  291.         void handleError(std::exception_ptr error);
  292.  
  293.         ap<uv::Stream> _stream;
  294.         Delegate * _delegate;
  295.         bool _inProgress = false;
  296.         bool _hadError = false;
  297.         bool _cancelled = false;
  298.         bool _canAppendBody = false;
  299.         bool _receivedAnything = false;
  300.         bool _requestConnectionClose = false;
  301.  
  302.         bool _stopReading = false;
  303.  
  304.         int _lastStatusCode = 0;
  305.         UniquePtr<ResponseParser> _parser;
  306.         ap<SimpleClientSession> _instance;
  307.     };
  308.  
  309. } // namespace http
  310. } // namespace fn
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement