| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_REQUEST_H_ | |
| #define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_REQUEST_H_ | |
| #include <map> | |
| #include <memory> | |
| #include <string> | |
| #include "base/macros.h" | |
| #include "base/strings/string_piece.h" | |
| #include "base/strings/string_util.h" | |
| #include "starboard/types.h" | |
| #include "url/gurl.h" | |
| namespace net { | |
| class HttpChunkedDecoder; | |
| namespace test_server { | |
| // Methods of HTTP requests supported by the test HTTP server. | |
| enum HttpMethod { | |
| METHOD_UNKNOWN, | |
| METHOD_GET, | |
| METHOD_HEAD, | |
| METHOD_POST, | |
| METHOD_PUT, | |
| METHOD_DELETE, | |
| METHOD_PATCH, | |
| METHOD_CONNECT, | |
| METHOD_OPTIONS, | |
| }; | |
| // Represents a HTTP request. Since it can be big, use scoped_ptr to pass it | |
| // instead of copying. However, the struct is copyable so tests can save and | |
| // examine a HTTP request. | |
| struct HttpRequest { | |
| struct CaseInsensitiveStringComparator { | |
| bool operator()(const std::string& left, const std::string& right) const { | |
| return base::CompareCaseInsensitiveASCII(left, right) < 0; | |
| } | |
| }; | |
| using HeaderMap = | |
| std::map<std::string, std::string, CaseInsensitiveStringComparator>; | |
| HttpRequest(); | |
| HttpRequest(const HttpRequest& other); | |
| ~HttpRequest(); | |
| // Returns a GURL as a convenience to extract the path and query strings. | |
| GURL GetURL() const; | |
| std::string relative_url; // Starts with '/'. Example: "/test?query=foo" | |
| GURL base_url; | |
| HttpMethod method; | |
| std::string method_string; | |
| std::string all_headers; | |
| HeaderMap headers; | |
| std::string content; | |
| bool has_content; | |
| }; | |
| // Parses the input data and produces a valid HttpRequest object. If there is | |
| // more than one request in one chunk, then only the first one will be parsed. | |
| // The common use is as below: | |
| // HttpRequestParser parser; | |
| // (...) | |
| // void OnDataChunkReceived(Socket* socket, const char* data, int size) { | |
| // parser.ProcessChunk(std::string(data, size)); | |
| // if (parser.ParseRequest() == HttpRequestParser::ACCEPTED) { | |
| // std::unique_ptr<HttpRequest> request = parser.GetRequest(); | |
| // (... process the request ...) | |
| // } | |
| class HttpRequestParser { | |
| public: | |
| // Parsing result. | |
| enum ParseResult { | |
| WAITING, // A request is not completed yet, waiting for more data. | |
| ACCEPTED, // A request has been parsed and it is ready to be processed. | |
| }; | |
| // Parser state. | |
| enum State { | |
| STATE_HEADERS, // Waiting for a request headers. | |
| STATE_CONTENT, // Waiting for content data. | |
| STATE_ACCEPTED, // Request has been parsed. | |
| }; | |
| HttpRequestParser(); | |
| ~HttpRequestParser(); | |
| // Adds chunk of data into the internal buffer. | |
| void ProcessChunk(const base::StringPiece& data); | |
| // Parses the http request (including data - if provided). | |
| // If returns ACCEPTED, then it means that the whole request has been found | |
| // in the internal buffer (and parsed). After calling GetRequest(), it will be | |
| // ready to parse another request. | |
| ParseResult ParseRequest(); | |
| // Retrieves parsed request. Can be only called, when the parser is in | |
| // STATE_ACCEPTED state. After calling it, the parser is ready to parse | |
| // another request. | |
| std::unique_ptr<HttpRequest> GetRequest(); | |
| private: | |
| HttpMethod GetMethodType(const std::string& token) const; | |
| // Parses headers and returns ACCEPTED if whole request was parsed. Otherwise | |
| // returns WAITING. | |
| ParseResult ParseHeaders(); | |
| // Parses request's content data and returns ACCEPTED if all of it have been | |
| // processed. Chunked Transfer Encoding is supported. | |
| ParseResult ParseContent(); | |
| // Fetches the next line from the buffer. Result does not contain \r\n. | |
| // Returns an empty string for an empty line. It will assert if there is | |
| // no line available. | |
| std::string ShiftLine(); | |
| std::unique_ptr<HttpRequest> http_request_; | |
| std::string buffer_; | |
| size_t buffer_position_; // Current position in the internal buffer. | |
| State state_; | |
| // Content length of the request currently being parsed. | |
| size_t declared_content_length_; | |
| std::unique_ptr<HttpChunkedDecoder> chunked_decoder_; | |
| DISALLOW_COPY_AND_ASSIGN(HttpRequestParser); | |
| }; | |
| } // namespace test_server | |
| } // namespace net | |
| #endif // NET_TEST_EMBEDDED_TEST_SERVER_HTTP_REQUEST_H_ |