@ -4,7 +4,7 @@
Lightweight C++ HTTP __client and server__ library based on [Asio ](https://github.com/chriskohlhoff/asio ) for __embedding__ purpose.
Lightweight C++ HTTP __client and server__ library based on [Asio ](https://github.com/chriskohlhoff/asio ) for __embedding__ purpose.
Please turn to [doc ](doc/ ) for more tutorials and guides. E.g., [Build Instructions ](doc/Build-Instructions.md ).
Please turn to [doc ](doc/ ) for more tutorials and guides. E.g., [Build Instructions ](doc/Build-Instructions.md ) and [Integrate Into Your Project ](doc/Integrate-Into-Your-Project.md ) .
Git repo: https://github.com/sprinfall/webcc. Please check this one instead of the forked for the latest features.
Git repo: https://github.com/sprinfall/webcc. Please check this one instead of the forked for the latest features.
@ -13,15 +13,18 @@ Git repo: https://github.com/sprinfall/webcc. Please check this one instead of t
* [Client API ](#client-api )
* [Client API ](#client-api )
* [A Complete Example ](#a-complete-example )
* [A Complete Example ](#a-complete-example )
* [Request Builder ](#request-builder )
* [Request Builder ](#request-builder )
* [HTTPS ](# request-builder )
* [HTTPS ](# https )
* [Invok e GitHub REST API](#invoke -github-rest-api)
* [Invok ing GitHub REST API](#invoking -github-rest-api)
* [Authorization ](#authorization )
* [Authorization ](#authorization )
* [Keep-Alive ](#keep-alive )
* [Keep-Alive (Persistent Connection) ](#keep-alive )
* [POST Request ](#post-request )
* [POST Request ](#post-request )
* [Download Files](#download -files)
* [Download ing Files](#download ing -files)
* [Upload Files](#upload -files)
* [Upload ing Files](#upload ing -files)
* [Server API ](#server-api )
* [Server API ](#server-api )
* [Hello World ](#hello-world )
* [A Minimal Server ](#a-minimal-server )
* [URL Route ](#url-route )
* [Running A Server ](#running-a-server )
* [Response Builder ](#response-builder )
* [REST Book Server ](#rest-book-server )
* [REST Book Server ](#rest-book-server )
## Overview
## Overview
@ -38,7 +41,6 @@ Git repo: https://github.com/sprinfall/webcc. Please check this one instead of t
- Timeout control
- Timeout control
- Source code follows [Google C++ Style ](https://google.github.io/styleguide/cppguide.html )
- Source code follows [Google C++ Style ](https://google.github.io/styleguide/cppguide.html )
- Automation tests and unit tests included
- Automation tests and unit tests included
- No memory leak detected by [VLD ](https://kinddragon.github.io/vld/ )
## Client API
## Client API
@ -110,7 +112,7 @@ session.Send(webcc::RequestBuilder{}.Get("https://httpbin.org/get")());
*NOTE: The HTTPS/SSL support requires the build option `WEBCC_ENABLE_SSL` to be enabled.*
*NOTE: The HTTPS/SSL support requires the build option `WEBCC_ENABLE_SSL` to be enabled.*
### Invoke GitHub REST API
### Invoking GitHub REST API
Listing GitHub public events is not a big deal:
Listing GitHub public events is not a big deal:
@ -131,7 +133,7 @@ In order to list the followers of an authorized GitHub user, you need either **B
```cpp
```cpp
session.Send(webcc::RequestBuilder{}.
session.Send(webcc::RequestBuilder{}.
Get("https://api.github.com/user/followers").
Get("https://api.github.com/user/followers").
AuthBasic(login, password) // Should be replaced by valid login and passwords
AuthBasic(< login> , < password> )
());
());
```
```
@ -140,13 +142,13 @@ Or **Token Authorization**:
```cpp
```cpp
session.Send(webcc::RequestBuilder{}.
session.Send(webcc::RequestBuilder{}.
Get("https://api.github.com/user/followers").
Get("https://api.github.com/user/followers").
AuthToken(token) // Should be replaced by a valid token
AuthToken(< token> )
());
());
```
```
### Keep-Alive
### Keep-Alive
Though **Keep-Alive** (i.e., persistent c onnection) is a good feature and enabled by default, you can turn it off:
Though **Keep-Alive** (i.e., Persistent C onnection) is a good feature and enabled by default, you can turn it off:
```cpp
```cpp
auto r = session.Send(webcc::RequestBuilder{}.
auto r = session.Send(webcc::RequestBuilder{}.
@ -168,27 +170,27 @@ session.Send(webcc::RequestBuilder{}.
());
());
```
```
### Download Files
### Downloading Files
Webcc has the ability to stream large response data to a file. This is especially useful when downloading files.
Webcc has the ability to stream large response data to a file. This is especially useful when downloading files.
```cpp
```cpp
auto r = session.Send(webcc::RequestBuilder{}.
auto r = session.Send(webcc::RequestBuilder{}.
Get("http://httpbin.org/image/jpeg")
Get("http://httpbin.org/image/jpeg")
(), true); // stream = true
(), /*stream=*/true);
// Move the streamed file to your destination.
// Move the streamed file to your destination.
r->file_body()->Move("./wolf.jpeg");
r->file_body()->Move("./wolf.jpeg");
```
```
### Upload Files
### Uploading Files
Streaming is also available for uploading:
Streaming is also available for uploading:
```cpp
```cpp
auto r = session.Send(webcc::RequestBuilder{}.
auto r = session.Send(webcc::RequestBuilder{}.
Post("http://httpbin.org/post").
Post("http://httpbin.org/post").
File(path) // Should be replaced by a valid file path
File(local/file/path)
());
());
```
```
@ -200,11 +202,17 @@ Please check the [examples](examples/) for more information.
## Server API
## Server API
### Hello World
### A Minimal Server
Run the following example, open your browser with `localhost:8080` , you should see "Hello, World!".
The following example is a minimal yet complete HTTP server.
Start it, open a browser with `localhost:8080` , you will see `Hello, World!` as response.
```cpp
```cpp
#include "webcc/logger.h"
#include "webcc/response_builder.h"
#include "webcc/server.h"
class HelloView : public webcc::View {
class HelloView : public webcc::View {
public:
public:
webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
@ -218,7 +226,7 @@ public:
int main() {
int main() {
try {
try {
webcc::Server server(8080) ;
webcc::Server server{ 8080 } ;
server.Route("/", std::make_shared< HelloView > ());
server.Route("/", std::make_shared< HelloView > ());
@ -232,6 +240,53 @@ int main() {
}
}
```
```
Every server program has a server object taking a port number (e.g., `8080` ) as argument. It listens to this port for incoming connections and requests.
### URL Route
The `Route()` method routes different URLs to different `views` .
You can route different URLs to the same view:
```cpp
server.Route("/", std::make_shared< HelloView > ());
server.Route("/hello", std::make_shared< HelloView > ());
```
Or even the same view object:
```cpp
auto view = std::make_shared< HelloView > ();
server.Route("/", view);
server.Route("/hello", view);
```
But normally a view only handles a specific URL (see the Book Server example).
The URL could be regular expressions. The Book Server example uses a regex URL to match against book IDs.
Finally, it's always suggested to explicitly specify the HTTP methods allowed for a route:
```cpp
server.Route("/", std::make_shared< HelloView > (), { "GET" });
```
### Running A Server
The last thing about server is `Run()` :
```cpp
void Run(std::size_t workers = 1, std::size_t loops = 1);
```
Workers are threads which will be waken to process the HTTP requests once they arrive. Theoretically, the more `workers` you have, the more concurrency you gain. In practice, you have to take the number of CPU cores into account and allocate a reasonable number for it.
The `loops` means the number of threads running the IO Context of Asio. Normally, one thread is good enough, but it could be more than that.
### Response Builder
The server API provides a helper class `ResponseBuilder` for the views to chain the parameters and finally build a response object. This is exactly the same strategy as `RequestBuilder` .
### REST Book Server
### REST Book Server
Suppose you want to create a book server and provide the following operations with RESTful API:
Suppose you want to create a book server and provide the following operations with RESTful API:
@ -330,7 +385,7 @@ int main(int argc, char* argv[]) {
// ...
// ...
try {
try {
webcc::Server server(8080) ;
webcc::Server server{ 8080 } ;
server.Route("/books",
server.Route("/books",
std::make_shared< BookListView > (),
std::make_shared< BookListView > (),