Part 1. Introducing Microservice APIs
Microservices today and how we got here
How do APIs help us drive microservices integrations?
1.3 Challenges of microservices architecture
Effective service decomposition
Microservices integration tests
Handling service unavailability
Tracing distributed transactions
Increased operational complexity and infrastructure overhead
1.4 Introducing documentation-driven development
1.5 Introducing the CoffeeMesh application
1.6 Who this book is for and what you will learn
2.1 Introducing the orders API specification
2.2 High-level architecture of the orders application
2.3 Implementing the API endpoints
2.4 Implementing data validation models with pydantic
2.5 Validating request payloads with pydantic
2.6 Marshalling and validating response payloads with pydantic
2.7 Adding an in-memory list of orders to the API
3.2 Microservices design principles
Database-per-service principle
Single Responsibility Principle
3.3 Service decomposition by business capability
Analyzing the business structure of CoffeeMesh
Decomposing microservices by business capabilities
3.4 Service decomposition by subdomains
Applying strategic analysis to CoffeeMesh
3.5 Decomposition by business capability vs. decomposition by subdomain
Part 2. Designing and building REST APIs
4 Principles of REST API design
4.1 What is REST?
4.2 Architectural constraints of REST applications
Separation of concerns: The client-server architecture principle
Make it scalable: The statelessness principle
Optimize for performance: The cacheability principle
Make it simple for the client: The layered system principle
Extendable interfaces: The code-on-demand principle
Keep it consistent: The uniform interface principle
4.3 Hypermedia as the engine of application state
4.4 Analyzing the maturity of an API with the Richardson maturity model
Level 1: Introducing the concept of resource
Level 2: Using HTTP methods and status codes
4.5 Structured resource URLs with HTTP methods
4.6 Using HTTP status codes to create expressive HTTP responses
Using HTTP status codes to report client errors in the request
Using HTTP status codes to report errors in the server
What are HTTP payloads, and when do we use them?
4.8 Designing URL query parameters
5 Documenting REST APIs with OpenAPI
5.1 Using JSON Schema to model data
5.2 Anatomy of an OpenAPI specification
5.3 Documenting the API endpoints
5.4 Documenting URL query parameters
5.5 Documenting request payloads
5.6 Refactoring schema definitions to avoid repetition
5.8 Creating generic responses
5.9 Defining the authentication scheme of the API
6 Building REST APIs with Python
6.1 Overview of the orders API
6.2 URL query parameters for the orders API
6.3 Validating payloads with unknown fields
6.4 Overriding FastAPI’s dynamically generated specification
6.5 Overview of the kitchen API
6.7 Initializing the web application for the API
6.8 Implementing the API endpoints
6.9 Implementing payload validation models with marshmallow
6.10 Validating URL query parameters
6.11 Validating data before serializing the response
6.12 Implementing an in-memory list of schedules
6.14 Overriding flask-smorest’s dynamically generated API specification
7 Service implementation patterns for microservices
7.1 Hexagonal architectures for microservices
7.2 Setting up the environment and the project structure
7.3 Implementing the database models
7.4 Implementing the repository pattern for data access
The case for the repository pattern: What is it, and why is it useful?
Implementing the repository pattern
7.5 Implementing the business layer
7.6 Implementing the unit of work pattern
7.7 Integrating the API layer and the service layer
Part 3. Designing and building GraphQL APIs
8.2 Introducing the products API
8.3 Introducing GraphQL’s type system
Creating property definitions with scalars
Modeling resources with object types
8.4 Representing collections of items with lists
8.5 Think graphs: Building meaningful connections between object types
Connecting types through edge properties
Creating connections with through types
8.6 Combining different types through unions and interfaces
8.7 Constraining property values with enumerations
8.8 Defining queries to serve data from the API
8.9 Altering the state of the server with mutations
9.1 Running a GraphQL mock server
9.2 Introducing GraphQL queries
Running queries with parameters
9.3 Using fragments in queries
9.4 Running queries with input parameters
9.6 Running multiple queries and query aliasing
Running multiple queries in the same request
9.8 Running parameterized queries and mutations
9.9 Demystifying GraphQL queries
9.10 Calling a GraphQL API with Python code
10 Building GraphQL APIs with Python
10.1 Analyzing the API requirements
10.2 Introducing the tech stack
10.3 Introducing Ariadne
10.4 Implementing the products API
Laying out the project structure
Creating an entry point for the GraphQL server
Implementing mutation resolvers
Building resolvers for custom scalar types
Part 4. Securing, testing, and deploying microservice APIs
11 API authorization and authentication
11.1 Setting up the environment for this chapter
11.2 Understanding authentication and authorization protocols
Understanding Open Authorization
11.3 Working with JSON Web Tokens
11.4 Adding authorization to the API server
Creating an authorization module
Creating an authorization middleware
11.5 Authorizing resource access
Updating the database to link users and orders
Restricting user access to their own resources
12 Testing and validating APIs
12.1 Setting up the environment for API testing
12.2 Testing REST APIs with Dredd
Installing and running Dredd’s default test suite
Customizing Dredd’s test suite with hooks
Using Dredd in your API testing strategy
12.3 Introduction to property-based testing
What is property-based testing?
The traditional approach to API testing
Property-based testing with Hypothesis
Using Hypothesis to test a REST API endpoint
12.4 Testing REST APIs with Schemathesis
Running Schemathesis’s default test suite
Using links to enhance Schemathesis’ test suite
12.5 Testing GraphQL APIs
Testing GraphQL APIs with Schemathesis
12.6 Designing your API testing strategy
13 Dockerizing microservice APIs
13.1 Setting up the environment for this chapter
13.2 Dockerizing a microservice
13.3 Running applications with Docker Compose
13.4 Publishing Docker builds to a container registry
14 Deploying microservice APIs with Kubernetes
14.1 Setting up the environment for this chapter
14.2 How Kubernetes works: The “CliffsNotes” version
14.3 Creating a Kubernetes cluster with EKS
14.4 Using IAM roles for Kubernetes service accounts
14.5 Deploying a Kubernetes load balancer
14.6 Deploying microservices to the Kubernetes cluster
Exposing services with ingress objects
14.7 Setting up a serverless database with AWS Aurora
Creating an Aurora Serverless database
Managing secrets in Kubernetes
Running the database migrations and connecting our service to the database
14.8 Updating the OpenAPI specification with the ALB’s hostname
14.9 Deleting the Kubernetes cluster
Appendix A. Types of web APIs and protocols
Appendix B. Managing an API’s life cycle
Appendix C. API authorization using an identity provider