diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:29:11 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:29:11 +0000 |
commit | c700fd159b4c094530244eb8e482376160823b5e (patch) | |
tree | 148e2676f0cf9fd95967757c26a7927c228ae9e2 /net/server | |
parent | f23a4495c988573cd612c6a58627c2eb3743bc23 (diff) | |
download | chromium_src-c700fd159b4c094530244eb8e482376160823b5e.zip chromium_src-c700fd159b4c094530244eb8e482376160823b5e.tar.gz chromium_src-c700fd159b4c094530244eb8e482376160823b5e.tar.bz2 |
Allow HttpServer response to include custom headers.
This is done by introducing a simple HttpServerResponseInfo class, and
changing the root HttpServer::Send to accept it instead of a status, data, and
mime type.
BUG=none
Review URL: https://chromiumcodereview.appspot.com/19637005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213227 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/server')
-rw-r--r-- | net/server/http_connection.cc | 21 | ||||
-rw-r--r-- | net/server/http_connection.h | 5 | ||||
-rw-r--r-- | net/server/http_server.cc | 20 | ||||
-rw-r--r-- | net/server/http_server.h | 2 | ||||
-rw-r--r-- | net/server/http_server_response_info.cc | 67 | ||||
-rw-r--r-- | net/server/http_server_response_info.h | 46 | ||||
-rw-r--r-- | net/server/http_server_response_info_unittest.cc | 51 | ||||
-rw-r--r-- | net/server/web_socket.cc | 22 |
8 files changed, 195 insertions, 39 deletions
diff --git a/net/server/http_connection.cc b/net/server/http_connection.cc index 66541fa..d964cb0 100644 --- a/net/server/http_connection.cc +++ b/net/server/http_connection.cc @@ -4,9 +4,8 @@ #include "net/server/http_connection.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" #include "net/server/http_server.h" +#include "net/server/http_server_response_info.h" #include "net/server/web_socket.h" #include "net/socket/stream_listen_socket.h" @@ -26,22 +25,8 @@ void HttpConnection::Send(const char* bytes, int len) { socket_->Send(bytes, len); } -void HttpConnection::Send(HttpStatusCode status_code, - const std::string& data, - const std::string& content_type) { - if (!socket_.get()) - return; - - socket_->Send(base::StringPrintf( - "HTTP/1.1 %d %s\r\n" - "Content-Type:%s\r\n" - "Content-Length:%d\r\n" - "\r\n", - status_code, - GetHttpReasonPhrase(status_code), - content_type.c_str(), - static_cast<int>(data.length()))); - socket_->Send(data); +void HttpConnection::Send(const HttpServerResponseInfo& response) { + Send(response.Serialize()); } HttpConnection::HttpConnection(HttpServer* server, StreamListenSocket* sock) diff --git a/net/server/http_connection.h b/net/server/http_connection.h index 488d528..b0e3766 100644 --- a/net/server/http_connection.h +++ b/net/server/http_connection.h @@ -15,6 +15,7 @@ namespace net { class HttpServer; +class HttpServerResponseInfo; class StreamListenSocket; class WebSocket; @@ -24,9 +25,7 @@ class HttpConnection { void Send(const std::string& data); void Send(const char* bytes, int len); - void Send(HttpStatusCode status_code, - const std::string& data, - const std::string& content_type); + void Send(const HttpServerResponseInfo& response); void Shift(int num_bytes); diff --git a/net/server/http_server.cc b/net/server/http_server.cc index b780739..3d54c40 100644 --- a/net/server/http_server.cc +++ b/net/server/http_server.cc @@ -13,6 +13,7 @@ #include "build/build_config.h" #include "net/server/http_connection.h" #include "net/server/http_server_request_info.h" +#include "net/server/http_server_response_info.h" #include "net/server/web_socket.h" #include "net/socket/tcp_listen_socket.h" @@ -45,14 +46,21 @@ void HttpServer::SendOverWebSocket(int connection_id, connection->web_socket_->Send(data); } +void HttpServer::SendResponse(int connection_id, + const HttpServerResponseInfo& response) { + HttpConnection* connection = FindConnection(connection_id); + if (connection == NULL) + return; + connection->Send(response); +} + void HttpServer::Send(int connection_id, HttpStatusCode status_code, const std::string& data, const std::string& content_type) { - HttpConnection* connection = FindConnection(connection_id); - if (connection == NULL) - return; - connection->Send(status_code, data, content_type); + HttpServerResponseInfo response(status_code); + response.SetBody(data, content_type); + SendResponse(connection_id, response); } void HttpServer::Send200(int connection_id, @@ -62,11 +70,11 @@ void HttpServer::Send200(int connection_id, } void HttpServer::Send404(int connection_id) { - Send(connection_id, HTTP_NOT_FOUND, std::string(), "text/html"); + SendResponse(connection_id, HttpServerResponseInfo::CreateFor404()); } void HttpServer::Send500(int connection_id, const std::string& message) { - Send(connection_id, HTTP_INTERNAL_SERVER_ERROR, message, "text/html"); + SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message)); } void HttpServer::Close(int connection_id) { diff --git a/net/server/http_server.h b/net/server/http_server.h index b5ba037..f434575 100644 --- a/net/server/http_server.h +++ b/net/server/http_server.h @@ -17,6 +17,7 @@ namespace net { class HttpConnection; class HttpServerRequestInfo; +class HttpServerResponseInfo; class IPEndPoint; class WebSocket; @@ -46,6 +47,7 @@ class HttpServer : public StreamListenSocket::Delegate, void AcceptWebSocket(int connection_id, const HttpServerRequestInfo& request); void SendOverWebSocket(int connection_id, const std::string& data); + void SendResponse(int connection_id, const HttpServerResponseInfo& response); void Send(int connection_id, HttpStatusCode status_code, const std::string& data, diff --git a/net/server/http_server_response_info.cc b/net/server/http_server_response_info.cc new file mode 100644 index 0000000..e4c6043 --- /dev/null +++ b/net/server/http_server_response_info.cc @@ -0,0 +1,67 @@ +// Copyright 2013 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. + +#include "net/server/http_server_response_info.h" + +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "net/http/http_request_headers.h" + +namespace net { + +HttpServerResponseInfo::HttpServerResponseInfo() : status_code_(HTTP_OK) {} + +HttpServerResponseInfo::HttpServerResponseInfo(HttpStatusCode status_code) + : status_code_(status_code) {} + +HttpServerResponseInfo::~HttpServerResponseInfo() {} + +// static +HttpServerResponseInfo HttpServerResponseInfo::CreateFor404() { + HttpServerResponseInfo response(HTTP_NOT_FOUND); + response.SetBody(std::string(), "text/html"); + return response; +} + +// static +HttpServerResponseInfo HttpServerResponseInfo::CreateFor500( + const std::string& body) { + HttpServerResponseInfo response(HTTP_INTERNAL_SERVER_ERROR); + response.SetBody(body, "text/html"); + return response; +} + +void HttpServerResponseInfo::AddHeader(const std::string& name, + const std::string& value) { + headers_.push_back(std::make_pair(name, value)); +} + +void HttpServerResponseInfo::SetBody(const std::string& body, + const std::string& content_type) { + DCHECK(body_.empty()); + body_ = body; + AddHeader(HttpRequestHeaders::kContentLength, + base::StringPrintf("%" PRIuS, body.length())); + AddHeader(HttpRequestHeaders::kContentType, content_type); +} + +std::string HttpServerResponseInfo::Serialize() const { + std::string response = base::StringPrintf( + "HTTP/1.1 %d %s\r\n", status_code_, GetHttpReasonPhrase(status_code_)); + Headers::const_iterator header; + for (header = headers_.begin(); header != headers_.end(); ++header) + response += header->first + ":" + header->second + "\r\n"; + + return response + "\r\n" + body_; +} + +HttpStatusCode HttpServerResponseInfo::status_code() const { + return status_code_; +} + +const std::string& HttpServerResponseInfo::body() const { + return body_; +} + +} // namespace net diff --git a/net/server/http_server_response_info.h b/net/server/http_server_response_info.h new file mode 100644 index 0000000..d6cedaa --- /dev/null +++ b/net/server/http_server_response_info.h @@ -0,0 +1,46 @@ +// Copyright 2013 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_SERVER_HTTP_SERVER_RESPONSE_INFO_H_ +#define NET_SERVER_HTTP_SERVER_RESPONSE_INFO_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "net/http/http_status_code.h" + +namespace net { + +class HttpServerResponseInfo { + public: + // Creates a 200 OK HttpServerResponseInfo. + HttpServerResponseInfo(); + explicit HttpServerResponseInfo(HttpStatusCode status_code); + ~HttpServerResponseInfo(); + + static HttpServerResponseInfo CreateFor404(); + static HttpServerResponseInfo CreateFor500(const std::string& body); + + void AddHeader(const std::string& name, const std::string& value); + + // This also adds an appropriate Content-Length header. + void SetBody(const std::string& body, const std::string& content_type); + + std::string Serialize() const; + + HttpStatusCode status_code() const; + const std::string& body() const; + + private: + typedef std::vector<std::pair<std::string, std::string> > Headers; + + HttpStatusCode status_code_; + Headers headers_; + std::string body_; +}; + +} // namespace net + +#endif // NET_SERVER_HTTP_SERVER_RESPONSE_INFO_H_ diff --git a/net/server/http_server_response_info_unittest.cc b/net/server/http_server_response_info_unittest.cc new file mode 100644 index 0000000..f7b8e25 --- /dev/null +++ b/net/server/http_server_response_info_unittest.cc @@ -0,0 +1,51 @@ +// Copyright 2013 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. + +#include "net/http/http_status_code.h" +#include "net/server/http_server_response_info.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +TEST(HttpServerResponseInfoTest, StatusLine) { + HttpServerResponseInfo response; + ASSERT_EQ(HTTP_OK, response.status_code()); + ASSERT_EQ("HTTP/1.1 200 OK\r\n\r\n", response.Serialize()); +} + +TEST(HttpServerResponseInfoTest, Headers) { + HttpServerResponseInfo response; + response.AddHeader("A", "1"); + response.AddHeader("A", "2"); + ASSERT_EQ("HTTP/1.1 200 OK\r\nA:1\r\nA:2\r\n\r\n", response.Serialize()); +} + +TEST(HttpServerResponseInfoTest, Body) { + HttpServerResponseInfo response; + ASSERT_EQ(std::string(), response.body()); + response.SetBody("body", "type"); + ASSERT_EQ("body", response.body()); + ASSERT_EQ( + "HTTP/1.1 200 OK\r\nContent-Length:4\r\nContent-Type:type\r\n\r\nbody", + response.Serialize()); +} + +TEST(HttpServerResponseInfoTest, CreateFor404) { + HttpServerResponseInfo response = HttpServerResponseInfo::CreateFor404(); + ASSERT_EQ( + "HTTP/1.1 404 Not Found\r\n" + "Content-Length:0\r\nContent-Type:text/html\r\n\r\n", + response.Serialize()); +} + +TEST(HttpServerResponseInfoTest, CreateFor500) { + HttpServerResponseInfo response = + HttpServerResponseInfo::CreateFor500("mess"); + ASSERT_EQ( + "HTTP/1.1 500 Internal Server Error\r\n" + "Content-Length:4\r\nContent-Type:text/html\r\n\r\nmess", + response.Serialize()); +} + +} // namespace net diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc index df5b0ae..7461085 100644 --- a/net/server/web_socket.cc +++ b/net/server/web_socket.cc @@ -16,6 +16,7 @@ #include "base/sys_byteorder.h" #include "net/server/http_connection.h" #include "net/server/http_server_request_info.h" +#include "net/server/http_server_response_info.h" namespace net { @@ -115,18 +116,16 @@ class WebSocketHixie76 : public net::WebSocket { std::string key2 = request.GetHeaderValue("Sec-WebSocket-Key2"); if (key1.empty()) { - connection->Send(net::HTTP_INTERNAL_SERVER_ERROR, - "Invalid request format. " - "Sec-WebSocket-Key1 is empty or isn't specified.", - "text/html"); + connection->Send(HttpServerResponseInfo::CreateFor500( + "Invalid request format. Sec-WebSocket-Key1 is empty or isn't " + "specified.")); return; } if (key2.empty()) { - connection->Send(net::HTTP_INTERNAL_SERVER_ERROR, - "Invalid request format. " - "Sec-WebSocket-Key2 is empty or isn't specified.", - "text/html"); + connection->Send(HttpServerResponseInfo::CreateFor500( + "Invalid request format. Sec-WebSocket-Key2 is empty or isn't " + "specified.")); return; } @@ -179,10 +178,9 @@ class WebSocketHybi17 : public WebSocket { std::string key = request.GetHeaderValue("Sec-WebSocket-Key"); if (key.empty()) { - connection->Send(net::HTTP_INTERNAL_SERVER_ERROR, - "Invalid request format. " - "Sec-WebSocket-Key is empty or isn't specified.", - "text/html"); + connection->Send(HttpServerResponseInfo::CreateFor500( + "Invalid request format. Sec-WebSocket-Key is empty or isn't " + "specified.")); return NULL; } return new WebSocketHybi17(connection, request, pos); |