calibre.leishi.io Open in urlscan Pro
2a06:98c1:3121::c  Public Scan

URL: https://calibre.leishi.io/read/76/pdf
Submission: On February 07 via manual from IN — Scanned from NL

Form analysis 0 forms found in the DOM

Text Content

Thumbnails Document Outline Attachments Layers
Foreword

Preface

What Is This Book About
Cloud-native applications
Working in a team
Who Is This Book For

Getting Started

Installing The Rust Toolchain
Compilation Targets
Release Channels
What Toolchains Do We Need?
Project Setup

IDEs
Rust-analyzer
IntelliJ Rust
What Should I Use?

Inner Development Loop
Faster Linking
cargo-watch

Continuous Integration

CI Steps
Tests
Code Coverage
Linting
Formatting
Security Vulnerabilities
Ready-to-go CI Pipelines

Building An Email Newsletter

Our Driving Example
Problem-based Learning
Course-correcting

What Should Our Newsletter Do?
Capturing Requirements: User Stories

Working In Iterations
Coming Up

Sign Up A New Subscriber
Our Strategy
Choosing A Web Framework

Our First Endpoint: A Basic Health Check
Wiring Up actix-web

Anatomy Of An actix-web Application
Server - HttpServer
Application - App
Endpoint - Route
Runtime - tokio
Implementing The Health Check Handler

Our First Integration Test
How Do You Test An Endpoint?
Where Should I Put My Tests?
Changing Our Project Structure For Easier Testing

Implementing Our First Integration Test

Polishing
Clean Up
Choosing A Random Port
Refocus

Working With HTML Forms
Refining Our Requirements
Capturing Our Requirements As Tests

Parsing Form Data From A POST Request
Extractors
Form And FromRequest
Serialisation In Rust: serde
Putting Everything Together

Storing Data: Databases
Choosing A Database

Choosing A Database Crate
Compile-time Safety
Query Interface
Async Support
Summary
Our Pick: sqlx
Integration Testing With Side-effects

Database Setup
Docker
Database Migrations

Writing Our First Query
Sqlx Feature Flags
Configuration Management
Connecting To Postgres
Our Test Assertion
Updating Our CI Pipeline

Persisting A New Subscriber
Application State In actix-web
actix-web Workers
The Data Extractor
The INSERT Query

Updating Our Tests
Test Isolation
Summary

Telemetry
Unknown Unknowns
Observability

Logging
The log Crate
actix-web's Logger Middleware
The Facade Pattern

Instrumenting POST /subscriptions
Interactions With External Systems
Think Like A User
Logs Must Be Easy To Correlate

Structured Logging
The tracing Crate
Migrating From log To tracing
tracing's Span
Instrumenting Futures
tracing's Subscriber
tracing-subscriber
tracing-bunyan-formatter
tracing-log
Removing Unused Dependencies
Cleaning Up Initialisation
Logs For Integration Tests
Cleaning Up Instrumentation Code - tracing::instrument
Protect Your Secrets - secrecy
Request Id
Leveraging The tracing Ecosystem
Summary

Going Live
We Must Talk About Deployments

Choosing Our Tools
Virtualisation: Docker
Hosting: DigitalOcean

A Dockerfile For Our Application
Dockerfiles
Build Context
Sqlx Offline Mode
Running An Image
Networking
Hierarchical Configuration
Database Connectivity

Optimising Our Docker Image
Docker Image Size
Caching For Rust Docker Builds

Deploy To DigitalOcean Apps Platform
Setup
App Specification
How To Inject Secrets Using Environment Variables
Connecting To Digital Ocean's Postgres Instance
Environment Variables In The App Spec
One Last Push

Reject Invalid Subscribers #1

Requirements
Domain Constraints
Security Constraints
First Implementation
Validation Is A Leaky Cauldron
Type-Driven Development

Ownership Meets Invariants
AsRef
Panics

Error As Values - Result
Converting parse To Return Result
Insightful Assertion Errors: claim
Unit Tests

Handling A Result
match
The ? Operator
400 Bad Request
The Email Format

The SubscriberEmail Type
Breaking The Domain Sub-Module
Skeleton Of A New Type

Property-based Testing
How To Generate Random Test Data With fake
quickcheck Vs proptest
Getting Started With quickcheck
Implementing The Arbitrary Trait

Payload Validation
Refactoring With TryFrom
Summary

Reject Invalid Subscribers #2

Confirmation Emails
Subscriber Consent
The Confirmation User Journey
The Implementation Strategy

EmailClient, Our Email Delivery Component

How To Send An Email
Choosing An Email API
The Email Client Interface

How To Write A REST Client Using reqwest
reqwest::Client
Connection Pooling
How To Reuse The Same reqwest::Client In actix-web
Configuring Our EmailClient

How To Test A REST Client
HTTP Mocking With wiremock
wiremock::MockServer
wiremock::Mock
The Intent Of A Test Should Be Clear
Mock expectations

First Sketch Of EmailClient::send_email
reqwest::Client::post
JSON body
Authorization Token
Executing The Request

Tightening Our Happy Path Test
Refactoring: Avoid Unnecessary Memory Allocations

Dealing With Failures
Error Status Codes
Timeouts
Refactoring: Test Helpers
Refactoring: Fail fast

Skeleton And Principles For A Maintainable Test Suite
Why Do We Write Tests?
Why Don't We Write Tests?
Test Code Is Still Code
Our Test Suite
Test Discovery
One Test File, One Crate
Sharing Test Helpers

Sharing Startup Logic
Extracting Our Startup Code
Testing Hooks In Our Startup Logic
Build An API Client
Summary
Refocus

Zero Downtime Deployments
Reliability

Deployment Strategies
Naive Deployment
Load Balancers
Rolling Update Deployments
Digital Ocean App Platform

Database Migrations
State Is Kept Outside The Application
Deployments And Migrations
Multi-step Migrations

A New Mandatory Column
Step 1: Add As Optional
Step 2: Start Using The New Column
Step 3: Backfill And Mark As NOT NULL
A New Table

Sending A Confirmation Email

A Static Email
Red test
Green test

A Static Confirmation Link
Red Test
Green Test
Refactor

Pending Confirmation
Red test
Green Test

Skeleton of GET /subscriptions/confirm
Red Test
Green Test

Connecting The Dots
Red Test
Green Test
Refactor

Subscription Tokens
Red Test
Green Test

Database Transactions
All Or Nothing
Transactions In Postgres
Transactions In Sqlx
Summary

Error Handling

What Is The Purpose Of Errors?

Internal Errors
Enable The Caller To React
Help An Operator To Troubleshoot

Errors At The Edge
Help A User To Troubleshoot
Summary

Error Reporting For Operators
Keeping Track Of The Error Root Cause

The Error Trait
Trait Objects
Error::source

Errors For Control Flow
Layering
Modelling Errors as Enums
The Error Type Is Not Enough
Removing The Boilerplate With thiserror

Avoid ``Ball Of Mud'' Error Enums
Using anyhow As Opaque Error Type
anyhow Or thiserror?
Who Should Log Errors?
Summary

Naive Newsletter Delivery
User Stories Are Not Set In Stone

Do Not Spam Unconfirmed Subscribers
Set Up State Using The Public API
Scoped Mocks
Green Test

All Confirmed Subscribers Receive New Issues
Composing Test Helpers
Implementation Strategy

Body Schema
Test Invalid Inputs
Fetch Confirmed Subscribers List

Send Newsletter Emails
context Vs with_context

Validation Of Stored Data
Responsibility Boundaries
Follow The Compiler
Remove Some Boilerplate
Limitations Of The Naive Approach
Summary

Securing Our API

Authentication

Drawbacks
Something They Know
Something They Have
Something They Are
Multi-factor Authentication

Password-based Authentication

Basic Authentication
Extracting Credentials
Password Verification - Naive Approach

Password Storage
No Need To Store Raw Passwords
Using A Cryptographic Hash
Preimage Attack
Naive Dictionary Attack
Dictionary Attack
Argon2
Salting
PHC String Format

Do Not Block The Async Executor
Tracing Context Is Thread-Local
User Enumeration

Is it safe?
Transport Layer Security (TLS)
Password Reset
Interaction Types

Machine To Machine
Client Credentials via OAuth2

Person Via Browser
Federated Identity
Machine to machine, on behalf of a person
Interlude: Next Steps

Login Forms
Serving HTML Pages

Login
HTML Forms
Redirect On Success

Processing Form Data
Building An authentication Module
Rejecting Invalid Credentials

Contextual Errors
Naive Approach
Query Parameters
Cross-Site Scripting (XSS)
Message Authentication Codes
Add An HMAC Tag To Protect Query Parameters
Verifying The HMAC Tag
Error Messages Must Be Ephemeral
What Is A Cookie?
An Integration Test For Login Failures
How To Set A Cookie In actix-web
An Integration Test For Login Failures - Part 2
How To Read A Cookie In actix-web
How To Delete A Cookie In actix-web
Cookie Security
actix-web-flash-messages

Sessions
Session-based Authentication
Session Store

Choosing A Session Store
Postgres
Redis

actix-session
Redis In Our Development Setup
Redis On Digital Ocean

Admin Dashboard
Redirect On Login Success
Session
A Typed Interface To Session
Reject Unauthenticated Users

Seed Users
Database Migration

Password Reset
Form Skeleton
Unhappy Path: New Passwords Do Not Match
Unhappy Path: The Current Password Is Invalid
Unhappy Path: The New Password Is Too Short
Logout
Happy Path: The Password Was Changed Successfully

Refactoring
How To Write An actix-web Middleware
Summary

Fault-tolerant Workflows
POST /admin/newsletters - A Refresher
Our Goal

Failure Modes
Invalid Inputs

Network I/O
Postgres
Postmark - API Errors
Application Crashes
Author Actions

Idempotency: An Introduction
Idempotency In Action: Payments
Idempotency Keys
Concurrent Requests
Requirements As Tests #1

Implementation Strategies
Stateful Idempotency: Save And Replay
Stateless Idempotency: Deterministic Key Generation
Time Is a Tricky Beast
Making A Choice

Idempotency Store
Which Database Should We Use?
Schema

Save And Replay
Read Idempotency Key
Retrieve Saved Responses

Save Responses
MessageBody and HTTP Streaming
Array Of Composite Postgres Types
Plug It In

Concurrent Requests
Requirements As Tests #2

Synchronization
Transaction Isolation Levels

Dealing With Errors
Distributed Transactions
Backward Recovery
Forward Recovery

Asynchronous Processing
newsletter_issues
issue_delivery_queue
POST /admin/newsletters
Email Processing
Worker loop
Launching Background Workers
Updating The Test Suite
Epilogue



Previous

Next
Highlight all Match case
Whole words

Presentation Mode Open Current View

Go to First Page Go to Last Page

Rotate Clockwise Rotate Counterclockwise

Text Selection Tool Hand Tool

Vertical Scrolling Horizontal Scrolling Wrapped Scrolling

No Spreads Odd Spreads Even Spreads

Document Properties…
Toggle Sidebar

Find
Previous

Next
of 433
Presentation Mode Open Current View

Tools
Zoom Out

Zoom In
Automatic Zoom Actual Size Page Fit Page Width 50% 75% 100% 125% 150% 200% 300%
400%

PRODUCTIONPRODUCTIONAN OPINIONATED INTRODUCTION TO BACKEND DEVELOPMENTLuca
PalmieriZERO TOIN RUSTSold tokartik.ynwa@gmail.com

ContentsForeword9Preface10What Is This Book About. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .10Cloud-native applications. . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .10Working in a team. . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11Who Is
This Book For. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . .111 Getting Started131.1 Installing The Rust Toolchain. . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .131.1.1 Compilation Targets. . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .131.1.2 Release
Channels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.131.1.3 What Toolchains Do We Need?. . . . . . . . . . . . . . . . . . . . . .
. . . . .141.2 Project Setup. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .141.3 IDEs. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .151.3.1 Rust-analyzer. . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .151.3.2 IntelliJ
Rust. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.151.3.3 What Should I Use?. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . .151.4 Inner Development Loop. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . .151.4.1 Faster Linking. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .161.4.2cargo-watch. . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .161.5 Continuous Integration. .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171.5.1 CI
Steps. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. .181.5.1.1 Tests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . .181.5.1.2 Code Coverage. . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . .181.5.1.3 Linting. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . .181.5.1.4 Formatting. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . .191.5.1.5 Security Vulnerabilities. . . . . . . . . . . .
. . . . . . . . . . . . . .191.5.2 Ready-to-go CI Pipelines. . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .202 Building An Email Newsletter212.1 Our
Driving Example. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . .212.1.1 Problem-based Learning. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . .212.1.2 Course-correcting. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .212.2 What Should Our Newsletter Do?. . . . . . . .
. . . . . . . . . . . . . . . . . . . . .212.2.1 Capturing Requirements: User
Stories. . . . . . . . . . . . . . . . . . . . . . .222.3 Working In Iterations.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .222.3.1
Coming Up. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. .233 Sign Up A New Subscriber243.1 Our Strategy. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .243.2 Choosing A Web Framework.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .243.3 Our First
Endpoint: A Basic Health Check. . . . . . . . . . . . . . . . . . . . . . .
.253.3.1 Wiring Upactix-web. . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . .253.3.2 Anatomy Of Anactix-webApplication. . . . . . . . . . . . . . .
. . . . . . .263.3.2.1 Server -HttpServer. . . . . . . . . . . . . . . . . . . .
. . . . . . . .263.3.2.2 Application -App. . . . . . . . . . . . . . . . . . . .
. . . . . . . . .263.3.2.3 Endpoint -Route. . . . . . . . . . . . . . . . . . .
. . . . . . . . . .273.3.2.4 Runtime -tokio. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . .273.3.3 Implementing The Health Check Handler. . . . . . .
. . . . . . . . . . . . . .303.4 Our First Integration Test. . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .323.4.1 How Do You Test An
Endpoint?. . . . . . . . . . . . . . . . . . . . . . . . . .323.4.2 Where Should
I Put My Tests?. . . . . . . . . . . . . . . . . . . . . . . . . . .333.4.3
Changing Our Project Structure For Easier Testing. . . . . . . . . . . . . . .
.343.5 Implementing Our First Integration Test. . . . . . . . . . . . . . . . .
. . . . . . . . .363.5.1 Polishing. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .391

















































































































































































































































































































































































































































More Information Less Information
Close


Enter the password to open this PDF file.


Cancel OK
File name:

-

File size:

-


Title:

-

Author:

-

Subject:

-

Keywords:

-

Creation Date:

-

Modification Date:

-

Creator:

-


PDF Producer:

-

PDF Version:

-

Page Count:

-

Page Size:

-


Fast Web View:

-

Close
Preparing document for printing…
0%
Cancel