OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "chrome/test/webdriver/dispatch.h" | 4 #include "chrome/test/webdriver/dispatch.h" |
5 | 5 |
6 #include <sstream> | 6 #include <sstream> |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "chrome/test/webdriver/commands/command.h" | 10 #include "chrome/test/webdriver/commands/command.h" |
11 | 11 |
12 namespace webdriver { | 12 namespace webdriver { |
13 | 13 |
14 // The standard HTTP Status codes are implemented below. Chrome uses | 14 // The standard HTTP Status codes are implemented below. Chrome uses |
15 // OK, See Other, Not Found, Method Not Allowed, and Internal Error. | 15 // OK, See Other, Not Found, Method Not Allowed, and Internal Error. |
16 // Internal Error, HTTP 500, is used as a catch all for any issue | 16 // Internal Error, HTTP 500, is used as a catch all for any issue |
17 // not covered in the JSON protocol. | 17 // not covered in the JSON protocol. |
18 void SendHttpOk(struct mg_connection* const connection, | 18 void SendHttpOk(struct mg_connection* const connection, |
19 const struct mg_request_info* const request_info, | 19 const struct mg_request_info* const request_info, |
20 const Response& response) { | 20 const Response& response) { |
21 const std::string json = response.ToJSON(); | 21 const std::string json = response.ToJSON(); |
22 std::ostringstream out; | 22 std::ostringstream out; |
23 out << "HTTP/1.1 200 OK\r\n" | 23 out << "HTTP/1.1 200 OK\r\n" |
24 << "Content-Length: " << strlen(json.c_str()) << "\r\n" | 24 << "Content-Length: " << strlen(json.c_str()) << "\r\n" |
25 << "Content-Type: application/json; charset=UTF-8\r\n" | 25 << "Content-Type: application/json; charset=UTF-8\r\n" |
26 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" | 26 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" |
27 << "Accept-Ranges: bytes\r\n" | 27 << "Accept-Ranges: bytes\r\n" |
28 << "Connection: close\r\n\r\n"; | 28 << "Connection: close\r\n\r\n"; |
29 if (strcmp(request_info->request_method, "HEAD") != 0) { | 29 if (strcmp(request_info->request_method, "HEAD") != 0) |
30 out << json << "\r\n"; | 30 out << json << "\r\n"; |
31 } | 31 VLOG(1) << out.str(); |
32 LOG(INFO) << out.str(); | |
33 mg_printf(connection, "%s", out.str().c_str()); | 32 mg_printf(connection, "%s", out.str().c_str()); |
34 } | 33 } |
35 | 34 |
36 void SendHttpSeeOther(struct mg_connection* const connection, | 35 void SendHttpSeeOther(struct mg_connection* const connection, |
37 const struct mg_request_info* const request_info, | 36 const struct mg_request_info* const request_info, |
38 const Response& response) { | 37 const Response& response) { |
39 const Value* value = response.value(); | 38 const Value* value = response.value(); |
40 CheckValueType(Value::TYPE_STRING, value); | 39 CheckValueType(Value::TYPE_STRING, value); |
41 std::string location; | 40 std::string location; |
42 if (!value->GetAsString(&location)) { | 41 if (!value->GetAsString(&location)) { |
43 NOTREACHED(); | 42 NOTREACHED(); |
44 } | 43 } |
45 | 44 |
46 std::ostringstream out; | 45 std::ostringstream out; |
47 out << "HTTP/1.1 303 See Other\r\n" | 46 out << "HTTP/1.1 303 See Other\r\n" |
48 << "Location: " << location << "\r\n" | 47 << "Location: " << location << "\r\n" |
49 << "Content-Type: text/html\r\n" | 48 << "Content-Type: text/html\r\n" |
50 << "Content-Length: 0\r\n\r\n"; | 49 << "Content-Length: 0\r\n\r\n"; |
51 LOG(INFO) << out.str(); | 50 VLOG(1) << out.str(); |
52 mg_printf(connection, "%s", out.str().c_str()); | 51 mg_printf(connection, "%s", out.str().c_str()); |
53 } | 52 } |
54 | 53 |
55 void SendHttpBadRequest(struct mg_connection* const connection, | 54 void SendHttpBadRequest(struct mg_connection* const connection, |
56 const struct mg_request_info* const request_info, | 55 const struct mg_request_info* const request_info, |
57 const Response& response) { | 56 const Response& response) { |
58 const std::string json = response.ToJSON(); | 57 const std::string json = response.ToJSON(); |
59 std::ostringstream out; | 58 std::ostringstream out; |
60 out << "HTTP/1.1 400 Bad Request\r\n" | 59 out << "HTTP/1.1 400 Bad Request\r\n" |
61 << "Content-Length: " << strlen(json.c_str()) << "\r\n" | 60 << "Content-Length: " << strlen(json.c_str()) << "\r\n" |
62 << "Content-Type: application/json; charset=UTF-8\r\n" | 61 << "Content-Type: application/json; charset=UTF-8\r\n" |
63 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" | 62 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" |
64 << "Accept-Ranges: bytes\r\n" | 63 << "Accept-Ranges: bytes\r\n" |
65 << "Connection: close\r\n\r\n"; | 64 << "Connection: close\r\n\r\n"; |
66 if (strcmp(request_info->request_method, "HEAD") != 0) { | 65 if (strcmp(request_info->request_method, "HEAD") != 0) |
67 out << json << "\r\n"; | 66 out << json << "\r\n"; |
68 } | 67 VLOG(1) << out.str(); |
69 LOG(INFO) << out.str(); | |
70 mg_printf(connection, "%s", out.str().c_str()); | 68 mg_printf(connection, "%s", out.str().c_str()); |
71 } | 69 } |
72 | 70 |
73 void SendHttpNotFound(struct mg_connection* const connection, | 71 void SendHttpNotFound(struct mg_connection* const connection, |
74 const struct mg_request_info* const request_info, | 72 const struct mg_request_info* const request_info, |
75 const Response& response) { | 73 const Response& response) { |
76 const std::string json = response.ToJSON(); | 74 const std::string json = response.ToJSON(); |
77 std::ostringstream out; | 75 std::ostringstream out; |
78 out << "HTTP/1.1 404 Not Found\r\n" | 76 out << "HTTP/1.1 404 Not Found\r\n" |
79 << "Content-Length: " << strlen(json.c_str()) << "\r\n" | 77 << "Content-Length: " << strlen(json.c_str()) << "\r\n" |
80 << "Content-Type: application/json; charset=UTF-8\r\n" | 78 << "Content-Type: application/json; charset=UTF-8\r\n" |
81 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" | 79 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" |
82 << "Accept-Ranges: bytes\r\n" | 80 << "Accept-Ranges: bytes\r\n" |
83 << "Connection: close\r\n\r\n"; | 81 << "Connection: close\r\n\r\n"; |
84 if (strcmp(request_info->request_method, "HEAD") != 0) { | 82 if (strcmp(request_info->request_method, "HEAD") != 0) |
85 out << json << "\r\n"; | 83 out << json << "\r\n"; |
86 } | 84 VLOG(1) << out.str(); |
87 LOG(INFO) << out.str(); | |
88 mg_printf(connection, "%s", out.str().c_str()); | 85 mg_printf(connection, "%s", out.str().c_str()); |
89 } | 86 } |
90 | 87 |
91 void SendHttpMethodNotAllowed(struct mg_connection* const connection, | 88 void SendHttpMethodNotAllowed(struct mg_connection* const connection, |
92 const struct mg_request_info* const request_info, | 89 const struct mg_request_info* const request_info, |
93 const Response& response) { | 90 const Response& response) { |
94 const Value* value = response.value(); | 91 const Value* value = response.value(); |
95 CheckValueType(Value::TYPE_LIST, value); | 92 CheckValueType(Value::TYPE_LIST, value); |
96 | 93 |
97 std::vector<std::string> allowed_methods; | 94 std::vector<std::string> allowed_methods; |
98 const ListValue* list_value = static_cast<const ListValue*>(value); | 95 const ListValue* list_value = static_cast<const ListValue*>(value); |
99 for (size_t i = 0; i < list_value->GetSize(); ++i) { | 96 for (size_t i = 0; i < list_value->GetSize(); ++i) { |
100 std::string method; | 97 std::string method; |
101 LOG_IF(WARNING, list_value->GetString(i, &method)) | 98 LOG_IF(WARNING, list_value->GetString(i, &method)) |
102 << "Ignoring non-string value at index " << i; | 99 << "Ignoring non-string value at index " << i; |
103 allowed_methods.push_back(method); | 100 allowed_methods.push_back(method); |
104 } | 101 } |
105 | 102 |
106 std::ostringstream out; | 103 std::ostringstream out; |
107 out << "HTTP/1.1 405 Method Not Allowed\r\n" | 104 out << "HTTP/1.1 405 Method Not Allowed\r\n" |
108 << "Content-Type: text/html\r\n" | 105 << "Content-Type: text/html\r\n" |
109 << "Content-Length: 0\r\n" | 106 << "Content-Length: 0\r\n" |
110 << "Allow: " << JoinString(allowed_methods, ',') << "\r\n\r\n"; | 107 << "Allow: " << JoinString(allowed_methods, ',') << "\r\n\r\n"; |
111 LOG(INFO) << out.str(); | 108 VLOG(1) << out.str(); |
112 mg_printf(connection, "%s", out.str().c_str()); | 109 mg_printf(connection, "%s", out.str().c_str()); |
113 } | 110 } |
114 | 111 |
115 void SendHttpInternalError(struct mg_connection* const connection, | 112 void SendHttpInternalError(struct mg_connection* const connection, |
116 const struct mg_request_info* const request_info, | 113 const struct mg_request_info* const request_info, |
117 const Response& response) { | 114 const Response& response) { |
118 const std::string json = response.ToJSON(); | 115 const std::string json = response.ToJSON(); |
119 std::ostringstream out; | 116 std::ostringstream out; |
120 out << "HTTP/1.1 500 Internal Server Error\r\n" | 117 out << "HTTP/1.1 500 Internal Server Error\r\n" |
121 << "Content-Length: " << strlen(json.c_str()) << "\r\n" | 118 << "Content-Length: " << strlen(json.c_str()) << "\r\n" |
122 << "Content-Type: application/json; charset=UTF-8\r\n" | 119 << "Content-Type: application/json; charset=UTF-8\r\n" |
123 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" | 120 << "Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept\r\n" |
124 << "Accept-Ranges: bytes\r\n" | 121 << "Accept-Ranges: bytes\r\n" |
125 << "Connection: close\r\n\r\n"; | 122 << "Connection: close\r\n\r\n"; |
126 if (strcmp(request_info->request_method, "HEAD") != 0) { | 123 if (strcmp(request_info->request_method, "HEAD") != 0) |
127 out << json << "\r\n"; | 124 out << json << "\r\n"; |
128 } | 125 VLOG(1) << out.str(); |
129 LOG(INFO) << out.str(); | |
130 mg_printf(connection, "%s", out.str().c_str()); | 126 mg_printf(connection, "%s", out.str().c_str()); |
131 } | 127 } |
132 | 128 |
133 // For every HTTP request from the mongoode server DispatchCommand will | 129 // For every HTTP request from the mongoode server DispatchCommand will |
134 // inspect the HTTP method call requested and execute the proper function | 130 // inspect the HTTP method call requested and execute the proper function |
135 // mapped from the class Command. | 131 // mapped from the class Command. |
136 void DispatchCommand(Command* const command, const std::string& method, | 132 void DispatchCommand(Command* const command, const std::string& method, |
137 Response* response) { | 133 Response* response) { |
138 if (command->DoesPost() && method == "POST") { | 134 if (command->DoesPost() && method == "POST") { |
139 if (command->Init(response)) { | 135 if (command->Init(response)) |
140 command->ExecutePost(response); | 136 command->ExecutePost(response); |
141 } | |
142 } else if (command->DoesGet() && method == "GET") { | 137 } else if (command->DoesGet() && method == "GET") { |
143 if (command->Init(response)) { | 138 if (command->Init(response)) |
144 command->ExecuteGet(response); | 139 command->ExecuteGet(response); |
145 } | |
146 } else if (command->DoesDelete() && method == "DELETE") { | 140 } else if (command->DoesDelete() && method == "DELETE") { |
147 if (command->Init(response)) { | 141 if (command->Init(response)) |
148 command->ExecuteDelete(response); | 142 command->ExecuteDelete(response); |
149 } | |
150 } else { | 143 } else { |
151 ListValue* methods = new ListValue; | 144 ListValue* methods = new ListValue; |
152 if (command->DoesPost()) { | 145 if (command->DoesPost()) |
153 methods->Append(Value::CreateStringValue("POST")); | 146 methods->Append(Value::CreateStringValue("POST")); |
154 } | |
155 if (command->DoesGet()) { | 147 if (command->DoesGet()) { |
156 methods->Append(Value::CreateStringValue("GET")); | 148 methods->Append(Value::CreateStringValue("GET")); |
157 methods->Append(Value::CreateStringValue("HEAD")); | 149 methods->Append(Value::CreateStringValue("HEAD")); |
158 } | 150 } |
159 if (command->DoesDelete()) { | 151 if (command->DoesDelete()) |
160 methods->Append(Value::CreateStringValue("DELETE")); | 152 methods->Append(Value::CreateStringValue("DELETE")); |
161 } | |
162 response->set_status(kMethodNotAllowed); | 153 response->set_status(kMethodNotAllowed); |
163 response->set_value(methods); // Assumes ownership. | 154 response->set_value(methods); // Assumes ownership. |
164 } | 155 } |
165 } | 156 } |
166 | 157 |
167 void SendResponse(struct mg_connection* const connection, | 158 void SendResponse(struct mg_connection* const connection, |
168 const struct mg_request_info* const request_info, | 159 const struct mg_request_info* const request_info, |
169 const Response& response) { | 160 const Response& response) { |
170 switch (response.status()) { | 161 switch (response.status()) { |
171 case kSuccess: | 162 case kSuccess: |
(...skipping 20 matching lines...) Expand all Loading... |
192 // responsible for inspecting the message body for details. | 183 // responsible for inspecting the message body for details. |
193 case kInternalServerError: | 184 case kInternalServerError: |
194 default: | 185 default: |
195 SendHttpInternalError(connection, request_info, response); | 186 SendHttpInternalError(connection, request_info, response); |
196 break; | 187 break; |
197 } | 188 } |
198 } | 189 } |
199 | 190 |
200 } // namespace webdriver | 191 } // namespace webdriver |
201 | 192 |
OLD | NEW |