Preface |
|
xii | |
Acknowledgments |
|
xv | |
About this book |
|
xvii | |
About the author |
|
xx | |
About the cover illustration |
|
xxi | |
|
PART 1 Introduction to Rust |
|
|
1 | (54) |
|
|
3 | (15) |
|
1.1 Batteries included: Rust's tooling |
|
|
4 | (5) |
|
|
9 | (2) |
|
1.3 Rust for web services |
|
|
11 | (5) |
|
1.4 Maintainability of Rust applications |
|
|
16 | (2) |
|
|
18 | (37) |
|
2.1 Following the Rust playbook |
|
|
19 | (24) |
|
Modeling your resources with structs |
|
|
21 | (2) |
|
|
23 | (1) |
|
Using documentation to solve errors |
|
|
24 | (5) |
|
|
29 | (2) |
|
Taking an excursion into moving, borrowing, and ownership |
|
|
31 | (3) |
|
Using and implementing traits |
|
|
34 | (8) |
|
|
42 | (1) |
|
2.2 Creating our web server |
|
|
43 | (12) |
|
Handling multiple requests at once |
|
|
44 | (1) |
|
Rust's asynchronous environment |
|
|
45 | (1) |
|
Rust's handling of async/await |
|
|
46 | (2) |
|
|
48 | (1) |
|
|
48 | (2) |
|
|
50 | (5) |
|
|
55 | (200) |
|
Create your first route handler |
|
|
57 | (1) |
|
3.1 Getting to know our web framework: Warp |
|
|
58 | (2) |
|
|
59 | (1) |
|
|
59 | (1) |
|
3.2 GET your first JSON response |
|
|
60 | (10) |
|
Align with your framework's way of thinking |
|
|
61 | (1) |
|
|
62 | (2) |
|
|
64 | (1) |
|
|
65 | (5) |
|
3.3 Handling CORS headers |
|
|
70 | (7) |
|
Returning CORS headers on the application level |
|
|
72 | (1) |
|
|
73 | (4) |
|
4 Implement a RESTful API |
|
|
77 | (38) |
|
4.1 GET questions from in-memory |
|
|
79 | (18) |
|
Setting up a mock database |
|
|
79 | (4) |
|
Preparing a set of test data |
|
|
83 | (2) |
|
Reading from the fake database |
|
|
85 | (4) |
|
|
89 | (4) |
|
|
93 | (4) |
|
4.2 POST, PUT, and DELETE questions |
|
|
97 | (13) |
|
Updating our data in a thread-safe way |
|
|
98 | (4) |
|
|
102 | (2) |
|
|
104 | (2) |
|
Handling malformed requests |
|
|
106 | (2) |
|
Removing questions from the storage |
|
|
108 | (2) |
|
4.3 POST answers via url-form-encoded |
|
|
110 | (5) |
|
Difference between url-form-encoded and JSON |
|
|
110 | (1) |
|
Adding answers via url-form-encoded |
|
|
111 | (4) |
|
|
115 | (26) |
|
5.1 Modularizing your code |
|
|
116 | (15) |
|
Using Rust's built-in mod system |
|
|
116 | (6) |
|
Practical folder structure for different use cases |
|
|
122 | (5) |
|
Creating libraries and sub-crates |
|
|
127 | (4) |
|
5.2 Documenting your code |
|
|
131 | (5) |
|
Using doc comments and private comments |
|
|
131 | (2) |
|
Adding code in your comments |
|
|
133 | (3) |
|
5.3 Linting and formatting your codebase |
|
|
136 | (5) |
|
Installing and using Clippy |
|
|
136 | (3) |
|
Formatting your code with Rustfmt |
|
|
139 | (2) |
|
6 Logging, tracing, and debugging |
|
|
141 | (36) |
|
6.1 Logging in your Rust application |
|
|
142 | (20) |
|
Implementing fogging in your web service |
|
|
145 | (6) |
|
Logging incoming HTTP requests |
|
|
151 | (4) |
|
|
155 | (7) |
|
6.2 Tracing in asynchronous applications |
|
|
162 | (6) |
|
Introducing the Tracing crate |
|
|
163 | (1) |
|
Integrating tracing in our application |
|
|
164 | (4) |
|
6.3 Debugging Rust applications |
|
|
168 | (9) |
|
Using GDB on the command line |
|
|
170 | (1) |
|
Debugging our web service with LLDB |
|
|
171 | (2) |
|
Using Visual Studio Code and LLDB |
|
|
173 | (4) |
|
7 Add a database to your application |
|
|
177 | (41) |
|
7.1 Setting up our example database |
|
|
178 | (1) |
|
7.2 Creating our first tables |
|
|
179 | (2) |
|
7.3 Working with a database crate |
|
|
181 | (8) |
|
Adding SQLx into our project |
|
|
184 | (1) |
|
Connecting Store to our database |
|
|
185 | (4) |
|
7.4 Reimplementing our route handlers |
|
|
189 | (15) |
|
Adding the database to get_questions |
|
|
190 | (7) |
|
Reimplementing the add_question route handler |
|
|
197 | (3) |
|
Adjusting the update and delete questions handler |
|
|
200 | (2) |
|
Updating the add_answer route |
|
|
202 | (2) |
|
7.5 Error handling and tracing database interactions |
|
|
204 | (6) |
|
7.6 Integrating SQL migrations |
|
|
210 | (4) |
|
7.7 Case study: Switching database management systems |
|
|
214 | (4) |
|
8 Integrate third-party APIs |
|
|
218 | (37) |
|
8.1 Preparing the codebase |
|
|
221 | (13) |
|
|
221 | (2) |
|
Getting to know our HTTP crate |
|
|
223 | (2) |
|
Adding an example HTTP call with Reqwest |
|
|
225 | (2) |
|
Handling errors for external API requests |
|
|
227 | (7) |
|
8.2 DeserializingJSON responses to structs |
|
|
234 | (7) |
|
Gathering API response information |
|
|
235 | (1) |
|
Creating types for our API responses |
|
|
236 | (5) |
|
8.3 Sending questions and answers to the API |
|
|
241 | (5) |
|
Rejadoring the add_question route handler |
|
|
241 | (3) |
|
Making profanity checks for updating questions |
|
|
244 | (1) |
|
Updating the add_answer route handler |
|
|
245 | (1) |
|
8.4 Handling timeouts and multiple requests at once |
|
|
246 | (9) |
|
Implementing a retry for external HTTP calls |
|
|
247 | (4) |
|
Executing futures concurrently or in parallel |
|
|
251 | (4) |
|
PART 3 Bring it into production |
|
|
255 | (109) |
|
11 Add authentication and authorization |
|
|
257 | (38) |
|
9.1 Adding authentication to our web service |
|
|
258 | (24) |
|
Creating the user concept |
|
|
260 | (2) |
|
|
262 | (2) |
|
Adding the registration endpoint |
|
|
264 | (3) |
|
|
267 | (2) |
|
Handling duplicate account errors |
|
|
269 | (6) |
|
Stateful vs. stateless authentication |
|
|
275 | (1) |
|
Adding the login endpoint |
|
|
276 | (4) |
|
Adding an expiry date to tokens |
|
|
280 | (2) |
|
9.2 Adding authorization middleware |
|
|
282 | (11) |
|
Migrating the database tables |
|
|
283 | (1) |
|
Creating token validation middleware |
|
|
283 | (5) |
|
Extending existing routes to handle account IDs |
|
|
288 | (5) |
|
|
293 | (2) |
|
10 Deploy your application |
|
|
295 | (30) |
|
10.1 Setting up your application through environment variables |
|
|
296 | (12) |
|
|
297 | (3) |
|
Accept command-line inputs for your application |
|
|
300 | (2) |
|
Read and parse environment variables into your web service |
|
|
302 | (6) |
|
10.2 Compiling your web service for different environments |
|
|
308 | (3) |
|
Development vs. release flag when building your binary |
|
|
308 | (1) |
|
Cross-compile your binary for different environments |
|
|
309 | (2) |
|
10.3 Using build.rs in your build process |
|
|
311 | (3) |
|
10.4 Creating the right Docker image for your web service |
|
|
314 | (11) |
|
Create a statically linked Docker image |
|
|
315 | (1) |
|
Set up a local Docker environment with docker-compose |
|
|
316 | (3) |
|
Extract the configuration of the web server into a new module |
|
|
319 | (6) |
|
11 Testing your Rust application |
|
|
325 | (39) |
|
11.1 Unit testing our business logic |
|
|
327 | (16) |
|
Testing the pagination logic and dealing with custom errors |
|
|
327 | (4) |
|
Testing the Config module with environment variables |
|
|
331 | (4) |
|
Testing the profanity module with a newly created mock server |
|
|
335 | (8) |
|
11.2 Testing our Warp filters |
|
|
343 | (4) |
|
11.3 Creating an integration testing setup |
|
|
347 | (17) |
|
Splitting up the codebase into a lib.rs and a binary |
|
|
349 | (3) |
|
Creating the integration-test crate and the oneshot server implementation |
|
|
352 | (3) |
|
Adding the registration test |
|
|
355 | (4) |
|
Unwinding in case of an error |
|
|
359 | (1) |
|
Testing the login and posting questions |
|
|
360 | (4) |
Appendix Thinking about security |
|
364 | (5) |
Index |
|
369 | |