Index: chrome/browser/chromeos/gdata/test_servers/http_request.h |
diff --git a/chrome/browser/chromeos/gdata/test_servers/http_request.h b/chrome/browser/chromeos/gdata/test_servers/http_request.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f181cdde72f40502de5235f432376a0c5cbb9727 |
--- /dev/null |
+++ b/chrome/browser/chromeos/gdata/test_servers/http_request.h |
@@ -0,0 +1,143 @@ |
+// 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 CHROME_BROWSER_CHROMEOS_GDATA_TEST_SERVERS_HTTP_REQUEST_H_ |
+#define CHROME_BROWSER_CHROMEOS_GDATA_TEST_SERVERS_HTTP_REQUEST_H_ |
+ |
+#include <map> |
+#include <string> |
+#include "base/basictypes.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/string_piece.h" |
+#include "googleurl/src/gurl.h" |
+ |
+namespace gdata { |
+namespace test_servers { |
+ |
+using base::StringPiece; |
+ |
+enum HTTP_METHOD { |
+ UNKNOWN, |
+ GET, |
+ HEAD, |
+ POST, |
+ PUT, |
+ DELETE, |
+ CUSTOM, |
satorux1
2012/10/16 03:12:18
What's custom? Please add a comment.
mtomasz
2012/11/08 13:29:59
Removed. Done.
|
+}; |
+ |
+// Wraps the HTTP request. Since it can be big, use scoped_ptr to pass it |
+// instead of copying. |
+class HttpRequest { |
satorux1
2012/10/16 03:12:18
class -> struct
mtomasz
2012/11/08 13:29:59
Done.
|
+ public: |
+ HttpRequest() : method(UNKNOWN) {} |
+ virtual ~HttpRequest() {} |
+ |
+ GURL url; |
+ HTTP_METHOD method; |
+ std::string raw_url; |
+ std::string protocol; |
satorux1
2012/10/16 03:12:18
Please add some comment about "protocol".
mtomasz
2012/11/08 13:29:59
eg. HTTP/1.1. Removed, since we support that only
|
+ std::map<std::string, std::string> headers; |
+ std::string content; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(HttpRequest); |
+}; |
+ |
+// Parses the input data and produces valid HttpRequest objects. The common |
+// use is as below: |
+// HttpRequestParser parser; |
+// (...) |
+// void OnDataChunkReceived(Socket* socket, const char* data, int size) { |
+// parser.ProcessChunk(data, size); |
+// STATE parser_state; |
+// while ((parser_state = ParseRequest()) == HttpRequestParser::READY) { |
+// scoped_ptr<HttpRequest> request = parser.GetRequest(); |
+// (... process the request ...) |
+// } |
+// if (parser_state == HttpRequestParser::SYNTAX_ERROR) |
+// socket.Close(); |
+class HttpRequestParser { |
+ public: |
+ // State of the parser. |
+ enum STATE { |
+ REQUEST_LINE, // Waiting for the request line, eg. GET / HTTP/1.1. |
+ HEADER_LINE, // Waiting for the header, eg. Host: google.com. |
+ DATA, // Waiting for data. |
+ READY, // Request has been received and should be processed. |
+ SYNTAX_ERROR, // A syntax error occured while processing the input. |
+ }; |
+ |
+ HttpRequestParser(); |
+ virtual ~HttpRequestParser(); |
+ |
+ // Adds chunk of data into the internal buffer. |
+ virtual void ProcessChunk(const char *data, int length); |
+ |
+ // Parses the http request (including data - if provided) according to: |
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html. |
+ // If returns READY, 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. If the parser enters the SYNTAX_ERROR |
+ // state, then no further parsing will possible. |
+ STATE ParseRequest(); |
+ |
+ // Retrieves parsed request. Can be only called, when the parser is in READY |
+ // state. You can call it once, since it clears the internal request builder |
+ // after a call. |
+ scoped_ptr<HttpRequest> GetRequest(); |
+ |
+ private: |
+ // This is a type of token for ShiftToken() method. IDENTIFIER is a token |
+ // ended with a space, HEADER_KEY is ended with colon, LINE is a token |
+ // including anything until the first \r\n occurence. |
+ enum SHIFT_TOKEN_TYPE { |
+ IDENTIFIER, |
+ HEADER_KEY, |
+ LINE, |
+ }; |
+ |
+ std::string buffer_; |
+ scoped_ptr<HttpRequest> request_builder_; |
satorux1
2012/10/16 06:39:48
request_builder_ -> http_request_
mtomasz
2012/11/08 13:29:59
Done.
|
+ STATE state_; |
+ |
+ int buffer_position_; |
satorux1
2012/10/16 06:39:48
This is an index in |buffer_|, right? I think this
mtomasz
2012/11/08 13:29:59
StringPiece is not perfect here I think. I would h
|
+ int crlf_position_; |
+ int crlf_checked_position_; |
+ int current_content_length_; |
+ |
+ // Receives a token from the internal buffer and shifts the buffer's pointer. |
+ // On failure, returns an empty ShiftPiece. |
+ virtual const StringPiece ShiftToken(SHIFT_TOKEN_TYPE token_type); |
+ |
+ // Shifts \r\n from the current position in the internal buffer. If not found, |
+ // then returns false. |
+ virtual bool ShiftCrLf(); |
+ |
+ // Shifts |length| number of bytes from the current position in the buffer. |
+ // Passed argument's value must be less or equal to available bytes in the |
+ // internal buffer (from the current position). The returned value contains |
+ // |length| bytes on success. On failure, an empty StringPiece is returned. |
+ virtual const StringPiece ShiftData(int length); |
+ |
+ // Skips all the spaces in the beginning of the current position of the |
+ // internal buffer. |
+ virtual void SkipSpaces(); |
+ |
+ // This helper function tells if there is a reason to process new data in |
+ // the internal buffer. Parsing the request is performed line by line for |
+ // headers, however for content it is parsed as soon as new chunk arrives. |
+ virtual bool ShouldParseBuffer(); |
+ |
+ // Helper function, updates the |crlf_position_| member with a valid value. |
+ // The member stores position of the first \r\n occurence in the internal |
+ // buffer after the previous one. Returns true if the CrLF sequence was |
+ // found. |
+ virtual bool FindNextCrLf(); |
+}; |
+ |
+} // namespace test_servers |
+} // namespace gdata |
+ |
+#endif // CHROME_BROWSER_CHROMEOS_GDATA_TEST_SERVERS_HTTP_REQUEST_H_ |