Skip to content

Commit

Permalink
Allow HttpServer response to include custom headers.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kkania@chromium.org committed Jul 23, 2013
1 parent f23a449 commit c700fd1
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 47 deletions.
1 change: 1 addition & 0 deletions cloud_print/gcp20/prototype/privet_http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "base/basictypes.h"
#include "base/values.h"
#include "net/http/http_status_code.h"
#include "net/server/http_server.h"
#include "net/server/http_server_request_info.h"

Expand Down
13 changes: 5 additions & 8 deletions content/browser/devtools/devtools_http_handler_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/server/http_server_request_info.h"
#include "net/server/http_server_response_info.h"
#include "ui/base/layout.h"
#include "url/gurl.h"
#include "webkit/common/user_agent/user_agent.h"
Expand Down Expand Up @@ -754,19 +755,15 @@ void DevToolsHttpHandlerImpl::SendJson(int connection_id,
scoped_ptr<base::Value> message_object(new base::StringValue(message));
base::JSONWriter::Write(message_object.get(), &json_message);

std::string response;
std::string mime_type = "application/json; charset=UTF-8";

response = base::StringPrintf("%s%s", json_value.c_str(), message.c_str());
net::HttpServerResponseInfo response(status_code);
response.SetBody(json_value + message, "application/json; charset=UTF-8");

thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&net::HttpServer::Send,
base::Bind(&net::HttpServer::SendResponse,
server_.get(),
connection_id,
status_code,
response,
mime_type));
response));
}

void DevToolsHttpHandlerImpl::Send200(int connection_id,
Expand Down
1 change: 1 addition & 0 deletions content/browser/devtools/devtools_http_handler_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
#include "content/public/browser/worker_service.h"
#include "net/http/http_status_code.h"
#include "net/server/http_server.h"

namespace base {
Expand Down
4 changes: 4 additions & 0 deletions net/net.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,7 @@
'../testing/gtest.gyp:gtest',
'../third_party/zlib/zlib.gyp:zlib',
'../url/url.gyp:url_lib',
'http_server',
'net',
'net_test_support'
],
Expand Down Expand Up @@ -1747,6 +1748,7 @@
'quic/quic_time_test.cc',
'quic/quic_utils_test.cc',
'quic/reliable_quic_stream_test.cc',
'server/http_server_response_info_unittest.cc',
'socket/buffered_write_stream_socket_unittest.cc',
'socket/client_socket_pool_base_unittest.cc',
'socket/deterministic_socket_data_unittest.cc',
Expand Down Expand Up @@ -2328,6 +2330,8 @@
'server/http_server.h',
'server/http_server_request_info.cc',
'server/http_server_request_info.h',
'server/http_server_response_info.cc',
'server/http_server_response_info.h',
'server/web_socket.cc',
'server/web_socket.h',
],
Expand Down
21 changes: 3 additions & 18 deletions net/server/http_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions net/server/http_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
namespace net {

class HttpServer;
class HttpServerResponseInfo;
class StreamListenSocket;
class WebSocket;

Expand All @@ -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);

Expand Down
20 changes: 14 additions & 6 deletions net/server/http_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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,
Expand All @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions net/server/http_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace net {

class HttpConnection;
class HttpServerRequestInfo;
class HttpServerResponseInfo;
class IPEndPoint;
class WebSocket;

Expand Down Expand Up @@ -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,
Expand Down
67 changes: 67 additions & 0 deletions net/server/http_server_response_info.cc
Original file line number Diff line number Diff line change
@@ -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
46 changes: 46 additions & 0 deletions net/server/http_server_response_info.h
Original file line number Diff line number Diff line change
@@ -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_
51 changes: 51 additions & 0 deletions net/server/http_server_response_info_unittest.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit c700fd1

Please sign in to comment.