//////////////////////////////////////////////////////////////////////////////// /// DISCLAIMER /// /// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany /// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// /// Copyright holder is ArangoDB GmbH, Cologne, Germany /// /// @author Dr. Frank Celler /// @author Achim Brandt //////////////////////////////////////////////////////////////////////////////// #ifndef ARANGOD_HTTP_SERVER_HTTP_COMM_TASK_H #define ARANGOD_HTTP_SERVER_HTTP_COMM_TASK_H 1 #include "Scheduler/SocketTask.h" #include "Basics/Mutex.h" #include "Basics/StringBuffer.h" #include "Basics/WorkItem.h" #include namespace arangodb { class HttpRequest; class HttpResponse; namespace rest { class HttpServer; class HttpCommTask : public SocketTask, public RequestStatisticsAgent { HttpCommTask(HttpCommTask const&) = delete; HttpCommTask const& operator=(HttpCommTask const&) = delete; public: static size_t const MaximalHeaderSize; static size_t const MaximalBodySize; static size_t const MaximalPipelineSize; static size_t const RunCompactEvery; public: HttpCommTask(HttpServer*, TRI_socket_t, ConnectionInfo&&, double keepAliveTimeout); protected: ~HttpCommTask(); public: // handles response void handleResponse(HttpResponse*); // handles simple errors void handleSimpleError(GeneralResponse::ResponseCode); void handleSimpleError(GeneralResponse::ResponseCode, int code, std::string const& errorMessage); // reads data from the socket bool processRead(); // sends more chunked data void sendChunk(basics::StringBuffer*); // chunking is finished void finishedChunked(); // task set up complete void setupDone(); private: // reads data from the socket void addResponse(HttpResponse*); /// check the content-length header of a request and fail it is broken bool checkContentLength(bool expectContentLength); // fills the write buffer void fillWriteBuffer(); // handles CORS options void processCorsOptions(); // processes a request void processRequest(); // clears the request object void clearRequest(); // resets the internal state /// /// this method can be called to clean up when the request handling aborts /// prematurely void resetState(bool close); // decides whether or not we should send back a www-authenticate /// header bool sendWwwAuthenticateHeader() const; protected: bool setup(Scheduler* scheduler, EventLoop loop) override; void cleanup() override; bool handleEvent(EventToken token, EventType events) override; void signalTask(TaskData*) override; protected: bool handleRead() override; void completedWriteBuffer() override; void handleTimeout() override; protected: // connection info ConnectionInfo _connectionInfo; // the underlying server HttpServer* const _server; // allow method override bool _allowMethodOverride; private: // write buffers std::deque _writeBuffers; // statistics buffers std::deque _writeBuffersStats; // current read position size_t _readPosition; // start of the body position size_t _bodyPosition; // body length size_t _bodyLength; // true if request is complete but not handled bool _requestPending; // true if a close has been requested by the client bool _closeRequested; // true if reading the request body bool _readRequestBody; // whether or not to allow credentialed requests (only CORS) bool _denyCredentials; // whether the client accepts deflate algorithm bool _acceptDeflate; // new request started bool _newRequest; // true if within a chunked response bool _isChunked; // the request with possible incomplete body HttpRequest* _request; // http version number used GeneralRequest::ProtocolVersion _httpVersion; // type of request (GET, POST, ...) GeneralRequest::RequestType _requestType; // value of requested URL std::string _fullUrl; // value of the HTTP origin header the client sent (if any, CORS only) std::string _origin; // start position of current request size_t _startPosition; // number of requests since last compactification size_t _sinceCompactification; // original body length size_t _originalBodyLength; // task ready std::atomic _setupDone; }; } } #endif