| Alex Vakulenko | 039da31 | 2015-02-03 08:58:55 -0800 | [diff] [blame^] | 1 | // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef WEBSERVER_LIBWEBSERV_SERVER_H_ |
| 6 | #define WEBSERVER_LIBWEBSERV_SERVER_H_ |
| 7 | |
| 8 | #include <map> |
| 9 | #include <memory> |
| 10 | #include <string> |
| 11 | |
| 12 | #include <base/callback_forward.h> |
| 13 | #include <base/macros.h> |
| 14 | #include <base/memory/ref_counted.h> |
| 15 | #include <base/strings/string_piece.h> |
| 16 | #include <chromeos/secure_blob.h> |
| 17 | #include <libwebserv/export.h> |
| 18 | #include <libwebserv/request_handler_interface.h> |
| 19 | |
| 20 | struct MHD_Daemon; |
| 21 | |
| 22 | namespace base { |
| 23 | class TaskRunner; |
| 24 | } // namespace base |
| 25 | |
| 26 | namespace libwebserv { |
| 27 | |
| 28 | // Top-level wrapper class around HTTP server and provides an interface to |
| 29 | // the web server. It allows the users to start the server and |
| 30 | // register request handlers. |
| 31 | class LIBWEBSERV_EXPORT Server final { |
| 32 | public: |
| 33 | Server(); |
| 34 | ~Server(); |
| 35 | |
| 36 | // Starts the server and makes it listen to HTTP requests on the given port. |
| 37 | // |
| 38 | // Note that a valid message loop must exist before calling Start. |
| 39 | bool Start(uint16_t port); |
| 40 | |
| 41 | // Starts the server and makes it listen to HTTPS requests on the given port. |
| 42 | // |
| 43 | // Note that a valid message loop must exist before calling StartWithTLS. |
| 44 | bool StartWithTLS(uint16_t port, |
| 45 | const chromeos::SecureBlob& private_key, |
| 46 | const chromeos::Blob& certificate); |
| 47 | |
| 48 | // Stops the server. |
| 49 | bool Stop(); |
| 50 | |
| 51 | // Adds a request handler for given |url|. If the |url| ends with a '/', this |
| 52 | // makes the handler respond to any URL beneath this path. |
| 53 | // Note that it is not possible to add a specific handler just for the root |
| 54 | // path "/". Doing so means "respond to any URL". |
| 55 | // |method| is optional request method verb, such as "GET" or "POST". |
| 56 | // If |method| is empty, the handler responds to any request verb. |
| 57 | // If there are more than one handler for a given request, the most specific |
| 58 | // match is chosen. For example, if there are the following handlers provided: |
| 59 | // - A["/foo/", ""] |
| 60 | // - B["/foo/bar", "GET"] |
| 61 | // - C["/foo/bar", ""] |
| 62 | // Here is what handlers are called when making certain requests: |
| 63 | // - GET("/foo/bar") => B[] |
| 64 | // - POST("/foo/bar") => C[] |
| 65 | // - PUT("/foo/bar") => C[] |
| 66 | // - GET("/foo/baz") => A[] |
| 67 | // - GET("/foo") => 404 Not Found |
| 68 | // This functions returns a handler ID which can be used later to remove |
| 69 | // the handler. |
| 70 | int AddHandler(const base::StringPiece& url, |
| 71 | const base::StringPiece& method, |
| 72 | std::unique_ptr<RequestHandlerInterface> handler); |
| 73 | |
| 74 | // Similar to AddHandler() above but the handler is just a callback function. |
| 75 | int AddHandlerCallback( |
| 76 | const base::StringPiece& url, |
| 77 | const base::StringPiece& method, |
| 78 | const base::Callback<RequestHandlerInterface::HandlerSignature>& |
| 79 | handler_callback); |
| 80 | |
| 81 | // Removes the handler with the specified |handler_id|. |
| 82 | // Returns false if the handler with the given ID is not found. |
| 83 | bool RemoveHandler(int handler_id); |
| 84 | |
| 85 | // Finds the handler ID given the exact match criteria. Note that using |
| 86 | // this function could cause unexpected side effects if there are more than |
| 87 | // one handler registered for given URL/Method parameters. |
| 88 | // It is better to remember the handler ID from AddHandler() method and use |
| 89 | // that ID to remove the handler, instead of looking the handler up using |
| 90 | // URL/Method. |
| 91 | int GetHandlerId(const base::StringPiece& url, |
| 92 | const base::StringPiece& method) const; |
| 93 | |
| 94 | // Finds a handler for given URL/Method. This method does the criteria |
| 95 | // matching and not exact match performed by GetHandlerId. This is the method |
| 96 | // used to look up the handler for incoming HTTP requests. |
| 97 | RequestHandlerInterface* FindHandler( |
| 98 | const base::StringPiece& url, |
| 99 | const base::StringPiece& method) const; |
| 100 | |
| 101 | private: |
| 102 | MHD_Daemon* server_ = nullptr; |
| 103 | scoped_refptr<base::TaskRunner> task_runner_; |
| 104 | |
| 105 | struct LIBWEBSERV_PRIVATE HandlerMapEntry { |
| 106 | std::string url; |
| 107 | std::string method; |
| 108 | std::unique_ptr<RequestHandlerInterface> handler; |
| 109 | }; |
| 110 | |
| 111 | std::map<int, HandlerMapEntry> request_handlers_; |
| 112 | int last_handler_id_{0}; |
| 113 | |
| 114 | friend class ServerHelper; |
| 115 | friend class Connection; |
| 116 | DISALLOW_COPY_AND_ASSIGN(Server); |
| 117 | }; |
| 118 | |
| 119 | } // namespace libwebserv |
| 120 | |
| 121 | #endif // WEBSERVER_LIBWEBSERV_SERVER_H_ |