Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(533)

Unified Diff: services/http_server/http_server.cc

Issue 715153004: Add support for HTTP handlers that are in self-contained apps. Also add an example app. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « services/http_server/BUILD.gn ('k') | services/http_server/public/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: services/http_server/http_server.cc
diff --git a/services/http_server/http_server.cc b/services/http_server/http_server.cc
index f45644a3dd2951aa5331782d8048bd6265d83bb1..f49fbb2a387356229773d679bd53c3f4a0b40d7b 100644
--- a/services/http_server/http_server.cc
+++ b/services/http_server/http_server.cc
@@ -19,12 +19,15 @@
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/application_runner.h"
+#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/environment/async_waiter.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/services/public/interfaces/network/network_service.mojom.h"
#include "services/http_server/http_request_parser.h"
#include "services/http_server/public/http_request.mojom.h"
#include "services/http_server/public/http_response.mojom.h"
+#include "services/http_server/public/http_server.mojom.h"
+#include "services/http_server/public/http_server_util.h"
#include "third_party/re2/re2/re2.h"
namespace mojo {
@@ -32,8 +35,7 @@ namespace examples {
class Connection;
-typedef base::Callback<HttpResponsePtr(
- const HttpRequest& request)> HandleRequestCallback;
+typedef base::Callback<void(HttpRequestPtr, Connection*)> HandleRequestCallback;
const char* GetHttpReasonPhrase(uint32_t code_in) {
switch (code_in) {
@@ -54,7 +56,7 @@ class Connection {
public:
// Callback called when a request is parsed. Response should be sent
// using Connection::SendResponse() on the |connection| argument.
- typedef base::Callback<void(Connection*, const HttpRequest&)> Callback;
+ typedef base::Callback<void(Connection*, HttpRequestPtr)> Callback;
Connection(TCPConnectedSocketPtr conn,
ScopedDataPipeProducerHandle sender,
@@ -116,7 +118,6 @@ class Connection {
uint32_t num_bytes = 0;
result = ReadDataRaw(receiver_.get(), NULL, &num_bytes,
MOJO_READ_DATA_FLAG_QUERY);
- printf("ReadDataRaw result = %d, num_bytes = %d\n", result, num_bytes);
if (!num_bytes)
return;
@@ -126,8 +127,7 @@ class Connection {
request_parser_.ProcessChunk(reinterpret_cast<char*>(buffer.get()));
if (request_parser_.ParseRequest() == HttpRequestParser::ACCEPTED) {
- HttpRequestPtr http_request = request_parser_.GetRequest();
- handle_request_callback_.Run(this, *http_request.get());
+ handle_request_callback_.Run(this, request_parser_.GetRequest());
}
}
@@ -235,35 +235,47 @@ class Connection {
size_t response_offset_;
};
-HttpResponsePtr CreateResponse(int code, const std::string& data) {
- HttpResponsePtr response = HttpResponse::New();
-
- ScopedDataPipeProducerHandle producer_handle;
- MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions),
- MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
- 1,
- data.size()};
- MojoResult result = CreateDataPipe(
- &options, &producer_handle, &response->body);
- DCHECK_EQ(MOJO_RESULT_OK, result);
- uint32_t num_bytes = data.size();
- result = WriteDataRaw(
- producer_handle.get(), data.c_str(), &num_bytes,
- MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
- DCHECK_EQ(MOJO_RESULT_OK, result);
- response->content_length = num_bytes;
- return response.Pass();
+void FooHandler(HttpRequestPtr request, Connection* connection) {
+ connection->SendResponse(CreateHttpResponse(200, "Foo"));
}
-HttpResponsePtr FooHandler(const HttpRequest& request) {
- return CreateResponse(200, "Foo").Pass();
+void BarHandler(HttpRequestPtr request, Connection* connection) {
+ connection->SendResponse(CreateHttpResponse(200, "Bar"));
}
-HttpResponsePtr BarHandler(const HttpRequest& request) {
- return CreateResponse(200, "Bar").Pass();
-}
+class HttpServerApp;
-class HttpServerApp : public ApplicationDelegate {
+class HttpServerServiceImpl : public InterfaceImpl<HttpServerService> {
+ public:
+ HttpServerServiceImpl(ApplicationConnection* connection,
+ HttpServerApp* app)
+ : app_(app) {}
+ virtual ~HttpServerServiceImpl();
+
+ private:
+ // HttpServerService:
+ void AddHandler(const mojo::String& path,
+ const mojo::Callback<void(bool)>& callback) override;
+ void RemoveHandler(const mojo::String& path,
+ const mojo::Callback<void(bool)>& callback) override;
+
+ void OnRequest(HttpRequestPtr request, Connection* connection) {
+ client()->OnHandleRequest(
+ request.Pass(),
+ base::Bind(&HttpServerServiceImpl::OnResponse, base::Unretained(this),
+ connection));
+ }
+
+ void OnResponse(Connection* connection, HttpResponsePtr response) {
+ connection->SendResponse(response.Pass());
+ }
+
+ HttpServerApp* app_;
+ std::vector<std::string> paths_;
+};
+
+class HttpServerApp : public ApplicationDelegate,
+ public InterfaceFactory<HttpServerService> {
public:
HttpServerApp() : weak_ptr_factory_(this) {}
virtual void Initialize(ApplicationImpl* app) override {
@@ -276,12 +288,42 @@ class HttpServerApp : public ApplicationDelegate {
}
// Add a handler for the given regex path.
- void AddHandler(const std::string& path,
+ bool AddHandler(const std::string& path,
const HandleRequestCallback& handler) {
+ for (auto& handler : handlers_) {
+ if (handler.pattern->pattern() == path)
+ return false;
+ }
+
handlers_.push_back(Handler(path, handler));
+ return true;
+ }
+
+ bool RemoveHandler(const std::string& path) {
+ for (auto i = handlers_.begin(); i != handlers_.end(); ++i) {
+ if (i->pattern->pattern() == path) {
+ handlers_.erase(i);
+ return true;
+ }
+ }
+
+ return false;
}
private:
+ // ApplicationDelegate:
+ bool ConfigureIncomingConnection(
+ ApplicationConnection* connection) override {
+ connection->AddService(this);
+ return true;
+ }
+
+ // InterfaceFactory<HttpServerService>:
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<HttpServerService> request) override {
+ mojo::BindToRequest(new HttpServerServiceImpl(connection, this), &request);
+ }
+
void OnSocketBound(NetworkErrorPtr err, NetAddressPtr bound_address) {
if (err->code != 0) {
printf("Bound err = %d\n", err->code);
@@ -349,7 +391,7 @@ class HttpServerApp : public ApplicationDelegate {
net_address->ipv4->addr[1] = 0;
net_address->ipv4->addr[2] = 0;
net_address->ipv4->addr[3] = 1;
- net_address->ipv4->port = 0;
+ net_address->ipv4->port = 80;
// Note that we can start using the proxies right away even thought the
// callbacks have not been called yet. If a previous step fails, they'll
@@ -364,17 +406,16 @@ class HttpServerApp : public ApplicationDelegate {
WaitForNextConnection();
}
- void HandleRequest(Connection* connection, const HttpRequest& request) {
- printf("HandleRequest for %s\n", request.relative_url.data());
+ void HandleRequest(Connection* connection, HttpRequestPtr request) {
for (auto& handler : handlers_) {
- if (RE2::FullMatch(request.relative_url.data(), *handler.pattern)) {
- connection->SendResponse(handler.callback.Run(request).Pass());
+ if (RE2::FullMatch(request->relative_url.data(), *handler.pattern)) {
+ handler.callback.Run(request.Pass(), connection);
return;
}
}
connection->SendResponse(
- CreateResponse(404, "No registered handler").Pass());
+ CreateHttpResponse(404, "No registered handler").Pass());
}
struct Handler {
@@ -408,6 +449,35 @@ class HttpServerApp : public ApplicationDelegate {
std::vector<Handler> handlers_;
};
+HttpServerServiceImpl::~HttpServerServiceImpl() {
+ for (auto& path : paths_)
+ app_->RemoveHandler(path);
+}
+
+void HttpServerServiceImpl::AddHandler(
+ const mojo::String& path,
+ const mojo::Callback<void(bool)>& callback) {
+ bool rv = app_->AddHandler(path,
+ base::Bind(&HttpServerServiceImpl::OnRequest,
+ base::Unretained(this)));
+ callback.Run(rv);
+ if (rv)
+ paths_.push_back(path);
+}
+
+void HttpServerServiceImpl::RemoveHandler(
+ const mojo::String& path,
+ const mojo::Callback<void(bool)>& callback) {
+ bool rv = app_->RemoveHandler(path);
+ callback.Run(rv);
+ for (auto i = paths_.begin(); i != paths_.end(); ++i) {
+ if (*i == path) {
+ paths_.erase(i);
+ break;
+ }
+ }
+}
+
} // namespace examples
} // namespace mojo
« no previous file with comments | « services/http_server/BUILD.gn ('k') | services/http_server/public/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698