Networking example
Below you can find source code of a networking
example that showcases usage
of the libbase
functionality for performing network requests. This example
is located in the /examples/networking/
directory in the repository and - if
enabled - will be built along the
libbase
library itself.
CMakeLists.txt
1add_executable(networking "")
2
3target_compile_options(networking
4 PRIVATE
5 ${LIBBASE_COMPILE_FLAGS}
6)
7
8target_link_libraries(networking
9 PRIVATE
10 libbase
11 libbase_net
12)
13
14target_sources(networking
15 PRIVATE
16 main.cc
17)
main.cc
1#include <thread>
2
3#include "base/bind.h"
4#include "base/callback.h"
5#include "base/init.h"
6#include "base/logging.h"
7#include "base/message_loop/run_loop.h"
8#include "base/net/init.h"
9#include "base/net/simple_url_loader.h"
10#include "base/net/url_request.h"
11#include "base/sequence_checker.h"
12#include "base/timer/elapsed_timer.h"
13
14void LogNetResponse(const base::net::ResourceResponse& response) {
15 LOG(INFO) << "Result: " << static_cast<int>(response.result);
16 LOG(INFO) << "HTTP code: " << response.code;
17 LOG(INFO) << "Final URL: " << response.final_url;
18 LOG(INFO) << "Downloaded " << response.data.size() << " bytes";
19 LOG(INFO) << "Latency: " << response.timing_connect.InMilliseconds() << "ms";
20 LOG(INFO) << "Headers";
21 for (const auto& [h, v] : response.headers) {
22 LOG(INFO) << " " << h << ": " << v;
23 }
24 LOG_IF(INFO, !response.data.empty())
25 << "Content:\n"
26 << std::string{response.data.begin(), response.data.end()};
27}
28
29void NetExampleGet() {
30 base::RunLoop run_loop{};
31
32 // Try to download and signal on finish
33 base::net::SimpleUrlLoader::DownloadUnbounded(
34 base::net::ResourceRequest{
35 "https://www.google.com/robots.txt",
36 base::net::kDefaultHeaders,
37 base::net::kNoPost,
38 true,
39 base::Seconds(5),
40 },
41 base::BindOnce([](base::net::ResourceResponse response) {
42 LogNetResponse(response);
43 }).Then(run_loop.QuitClosure()));
44
45 // Runs all tasks until the quit callback is called
46 run_loop.Run();
47}
48
49void NetExamplePost() {
50 base::RunLoop run_loop{};
51
52 // Try to download and signal on finish
53 const std::string data_str = "{\"key\": \"value\"}";
54 base::net::SimpleUrlLoader::DownloadUnbounded(
55 base::net::ResourceRequest{
56 "https://httpbin.org/post",
57 {"Content-Type: application/json"},
58 std::vector<uint8_t>{data_str.begin(), data_str.end()},
59 false,
60 base::Seconds(5),
61 },
62 base::BindOnce([](base::net::ResourceResponse response) {
63 LogNetResponse(response);
64 }).Then(run_loop.QuitClosure()));
65
66 run_loop.Run();
67}
68
69class UrlRequestExampleUser : public base::net::UrlRequest::Client {
70 public:
71 UrlRequestExampleUser(base::OnceClosure finished_closure)
72 : finished_closure_(std::move(finished_closure)), request_(this) {}
73
74 void Download(base::net::ResourceRequest request) {
75 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
76 request_.Start(std::move(request));
77 }
78
79 void OnResponseStarted(const base::net::UrlRequest* request,
80 int code,
81 std::string final_url,
82 std::map<std::string, std::string> headers) override {
83 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
84 DCHECK_EQ(request, &request_);
85
86 LOG(INFO) << __FUNCTION__ << "() code: " << code;
87 LOG(INFO) << __FUNCTION__ << "() final_url: " << final_url;
88 for (const auto& [k, v] : headers) {
89 LOG(INFO) << __FUNCTION__ << "() header[" << k << "]: " << v;
90 }
91 }
92
93 void OnWriteData(const base::net::UrlRequest* request,
94 std::vector<uint8_t> chunk) override {
95 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
96 DCHECK_EQ(request, &request_);
97
98 LOG(INFO) << __FUNCTION__ << "() received bytes: " << chunk.size();
99 }
100
101 void OnRequestFinished(const base::net::UrlRequest* request,
102 base::net::Result result) override {
103 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
104 DCHECK_EQ(request, &request_);
105
106 LOG(INFO) << __FUNCTION__ << "() result: " << static_cast<int>(result);
107 std::move(finished_closure_).Run();
108 }
109
110 private:
111 SEQUENCE_CHECKER(sequence_checker_);
112 base::OnceClosure finished_closure_;
113 base::net::UrlRequest request_;
114};
115
116void NetExampleUrlRequest() {
117 base::RunLoop run_loop;
118
119 UrlRequestExampleUser url_request_user{run_loop.QuitClosure()};
120 url_request_user.Download(base::net::ResourceRequest{
121 "https://www.google.com/robots.txt",
122 base::net::kDefaultHeaders,
123 base::net::kNoPost,
124 false,
125 base::Seconds(5),
126 });
127
128 run_loop.Run();
129}
130
131int main(int argc, char* argv[]) {
132 base::Initialize(argc, argv, base::InitOptions{});
133 base::net::Initialize(base::net::InitOptions{});
134
135 const auto timer = base::ElapsedTimer{};
136
137 NetExampleGet();
138 NetExamplePost();
139 NetExampleUrlRequest();
140
141 LOG(INFO) << "Example finished in " << timer.Elapsed().InMillisecondsF()
142 << "ms";
143
144 base::net::Deinitialize();
145 base::Deinitialize();
146 return 0;
147}