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..9764fec4f638c35299d8ff74b16e0423337e47d4 |
--- /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 "googleurl/src/gurl.h" |
+ |
+namespace gdata { |
+namespace test_servers { |
+ |
+enum HTTP_METHOD { |
satorux1
2012/10/12 08:29:18
HttpMethod
mtomasz
2012/10/12 11:09:46
Here I am confused. On chromium website they sugge
satorux1
2012/10/16 03:12:18
MACRO_STYLE is for members. The enum types should
|
+ UNKNOWN = 0, |
+ OPTIONS = 1, |
+ GET = 2, |
+ HEAD = 4, |
satorux1
2012/10/12 08:29:18
The following would be better:
OPTIONS = 1 << 0,
mtomasz
2012/10/12 11:09:46
I wanted to use it in the future for bit sets, lik
|
+ POST = 8, |
+ PUT = 16, |
+ DELETE = 32, |
+ TRACE = 64, |
+ CONNECT = 128, |
+ CUSTOM = 256 |
satorux1
2012/10/12 08:29:18
Do we need all the method types? I'd suggest to re
mtomasz
2012/10/12 11:09:46
Done.
|
+}; |
+ |
+// Wraps the HTTP request. Since it can be big, use scoped_ptr to pass it |
+// instead of copying. |
+class HttpRequest { |
+ public: |
+ HttpRequest() : method(UNKNOWN) {} |
+ virtual ~HttpRequest() {} |
+ |
+ GURL url; |
+ HTTP_METHOD method; |
+ std::string raw_url; |
+ std::string protocol; |
+ 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 { |
satorux1
2012/10/12 08:29:18
Enum names should look like State
|
+ REQUEST_LINE, |
+ HEADER_LINE, |
+ DATA, |
+ READY, |
+ SYNTAX_ERROR |
satorux1
2012/10/12 08:29:18
Please add , at the end. it makes slightly easier
mtomasz
2012/10/12 11:09:46
Done.
|
+ }; |
satorux1
2012/10/12 08:29:18
Please add comments for each state.
mtomasz
2012/10/12 11:09:46
Done.
|
+ |
+ 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_; |
+ STATE state_; |
+ |
+ int buffer_position_; |
+ int crlf_position_; |
+ int crlf_checked_position_; |
+ int current_content_length_; |
+ |
+ // Received a token from the internal buffer and shifts the buffer's pointer. |
+ virtual std::string 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). Returned pointer is not a |
+ // string, but a pointer to the requested data. Especially, it is not null- |
+ // terminated. |
+ virtual const char* ShiftData(int length); |
satorux1
2012/10/12 08:29:18
You might want to use StringPiece instead of char*
mtomasz
2012/10/12 11:09:46
Done.
|
+ |
+ // 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_ |