| 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 |