This commit is contained in:
556
Career/API/API Architecture.md
Executable file
556
Career/API/API Architecture.md
Executable file
@@ -0,0 +1,556 @@
|
||||
---
|
||||
note type:
|
||||
- note
|
||||
- api
|
||||
date: 2026-06-03
|
||||
done: false
|
||||
---
|
||||
**Z notes on API architecture - companion to [[APIM]]
|
||||
|
||||
# 1\. What is API Architecture?
|
||||
|
||||
API architecture is the set of rules, patterns, and structural decisions that govern how APIs are designed, exposed, consumed, and maintained across a system. It sits above individual API implementation - it's about **how APIs fit together** as a platform.
|
||||
|
||||
In Microlise's context: the APIOps pipeline, the APIM gateway layer, OpenShift clusters, and the OpenAPI specs are all artefacts **of** an architectural decision. Understanding the architecture behind them makes the pipeline choices make sense.
|
||||
|
||||
# 2\. Architectural Styles
|
||||
|
||||
Different styles define how clients and servers communicate. These are not mutually exclusive - a platform can expose multiple styles simultaneously (e.g. REST externally, gRPC internally).
|
||||
|
||||
## 2.1 REST (Representational State Transfer)
|
||||
|
||||
The dominant style for public and partner APIs. Key constraints:
|
||||
|
||||
- **Stateless**: Each request must contain all the context needed to fulfil it. No session state is stored server-side between calls.
|
||||
|
||||
- **Resource-oriented**: APIs are modelled around nouns (resources), not verbs (actions).
|
||||
|
||||
- Good: `GET /vehicles/{id}`
|
||||
- Bad: `POST /getVehicle`
|
||||
|
||||
- **Uniform interface**: Standard HTTP verbs carry semantic meaning:
|
||||
|
||||
| Verb | Meaning |
|
||||
| ------ | --------------------------- |
|
||||
| GET | Read a resource |
|
||||
| POST | Create a resource |
|
||||
| PUT | Replace a resource entirely |
|
||||
| PATCH | Partially update a resource |
|
||||
| DELETE | Remove a resource |
|
||||
|
||||
|
||||
- **Layered system**: Clients don't know if they're talking to the real backend or a gateway/proxy/cache. This is exactly what Microlise's APIM layer provides.
|
||||
|
||||
- **Cacheable**: Responses should declare whether they can be cached, enabling CDN and client-side optimisation.
|
||||
|
||||
OpenAPI Specification (OAS/Swagger) is the standard way to **describe** a REST API. The `spec` referred to throughout the APIOps pipeline is this document.
|
||||
|
||||
## 2.2 GraphQL
|
||||
|
||||
A query language for APIs developed by Meta. Instead of fixed endpoints, clients send a query describing exactly what data they need.
|
||||
|
||||
- Single endpoint: `POST /graphql`
|
||||
- Client drives the shape of the response - no over-fetching or under-fetching.
|
||||
- Good for: complex, interconnected data models; front-end teams who iterate quickly.
|
||||
- Trade-off: harder to cache, more complex server-side resolver logic, linting/governance is less mature than OAS.
|
||||
|
||||
Not currently the Microlise APIM pattern but worth understanding as a contrast.
|
||||
|
||||
## 2.3 gRPC (Google Remote Procedure Call)
|
||||
|
||||
Uses Protocol Buffers (protobuf) as the interface definition language and HTTP/2 as transport.
|
||||
|
||||
- Strongly typed contracts defined in `.proto` files.
|
||||
- Extremely high performance - binary serialisation, multiplexed streams.
|
||||
- Ideal for: internal service-to-service calls, microservices, high-throughput scenarios.
|
||||
- Trade-off: not human-readable, harder to test with standard tooling (curl, Postman), less browser-friendly.
|
||||
|
||||
Think of gRPC as what might live **behind** an API gateway - internal communication between microservices - while REST/OAS faces outward toward customers.
|
||||
|
||||
## 2.4 AsyncAPI / Event-Driven APIs
|
||||
|
||||
Not all APIs are request-response. Event-driven APIs use messaging patterns:
|
||||
|
||||
- **Webhooks**: Server POSTs to a client-registered URL when an event occurs.
|
||||
- **WebSockets**: Persistent bi-directional connection between client and server.
|
||||
- **Server-Sent Events (SSE)**: One-way stream from server to client.
|
||||
- **Message queues** (Kafka, RabbitMQ, Azure Service Bus): Decoupled async messaging.
|
||||
|
||||
AsyncAPI is the OAS equivalent for event-driven interfaces - a specification format for documenting these contracts.
|
||||
|
||||
# 3\. API Gateway Pattern
|
||||
|
||||
This is the core of what APIM implements. An API gateway sits as an intermediary between consumers (customers, internal teams) and backend services.
|
||||
|
||||
``` mermaid
|
||||
flowchart TD
|
||||
EC[External Consumer]
|
||||
GW["API Gateway / APIM
|
||||
────────────────────
|
||||
Auth · Rate Limiting
|
||||
Transforms · Routing
|
||||
Logging · Caching"]
|
||||
SA["Service A\n(OpenShift)"]
|
||||
SB["Service B\n(OpenShift)"]
|
||||
SC["Service C\n(OpenShift)"]
|
||||
|
||||
EC --> GW
|
||||
GW --> SA
|
||||
GW --> SB
|
||||
GW --> SC
|
||||
```
|
||||
|
||||
## 3.1 What the gateway does
|
||||
|
||||
| Concern | What it means |
|
||||
| --------------------------- | ------------------------------------------------------------------------- |
|
||||
| **Authentication** | Verifies who the caller is (OAuth2 tokens, API keys, mutual TLS) |
|
||||
| **Authorisation** | Determines what the caller is allowed to do (scopes, claims) |
|
||||
| **Rate limiting** | Caps requests per second/minute/hour per consumer or globally |
|
||||
| **Throttling** | Gracefully slows or queues excess requests rather than rejecting them |
|
||||
| **Request transformation** | Rewrites headers, payloads, or paths before forwarding to backends |
|
||||
| \*Response transformation\* | Strips internal fields, reformats responses for the consumer contract |
|
||||
| **Routing** | Directs traffic to the correct backend based on path, headers, or content |
|
||||
| **Load balancing** | Distributes traffic across backend instances |
|
||||
| **Caching** | Stores responses to reduce backend load for idempotent requests |
|
||||
| **Observability** | Centralises access logs, metrics, and tracing across all APIs |
|
||||
|
||||
In Azure APIM specifically, these concerns are implemented as **policies** - XML-based declarative rules that run at gateway level.
|
||||
|
||||
## 3.2 Reverse Proxy vs API Gateway
|
||||
|
||||
The Microlise notes reference a Reverse Proxy pipeline alongside APIM. These are related but distinct:
|
||||
|
||||
| Aspect | Reverse Proxy | API Gateway |
|
||||
| ------------------ | ------------------------------ | ---------------------------------------------- |
|
||||
| Primary purpose | Routing and TLS termination | Full API lifecycle management |
|
||||
| Protocol awareness | Layer 4/7 (TCP/HTTP) | Layer 7, API-aware (understands REST, OAS) |
|
||||
| Policy engine | Minimal (Nginx/HAProxy config) | Rich (auth, transforms, quotas, subscriptions) |
|
||||
| Developer portal | No | Yes - consumer-facing API catalogue |
|
||||
| Examples | Nginx, HAProxy, Traefik | Azure APIM, Kong, AWS API Gateway |
|
||||
|
||||
A common pattern (and likely what Microlise uses) is: Reverse proxy handles ingress and TLS termination → traffic forwarded to APIM for policy enforcement → APIM routes to OpenShift services.
|
||||
|
||||
# 4\. API Design Principles
|
||||
|
||||
## 4.1 Contract-First Design
|
||||
|
||||
Define the OpenAPI spec **before** writing implementation code. The spec is the source of truth.
|
||||
|
||||
Benefits:
|
||||
|
||||
- Frontend/consumer teams can mock and build against the spec immediately.
|
||||
- Linting pipelines (like the one in APIOps gated build) can enforce governance before any code ships.
|
||||
- Breaking change detection is automated.
|
||||
|
||||
The APIOps pipeline enforces this: the spec is committed to source control, linted, reviewed by the API Governance Council, and only then does the publish pipeline sync it to APIM environments.
|
||||
|
||||
## 4.2 Versioning Strategies
|
||||
|
||||
APIs evolve. Versioning prevents changes from breaking existing consumers.
|
||||
|
||||
| Strategy | Example | Trade-offs |
|
||||
| --------------------- | ------------------------------------- | --------------------------------------------------- |
|
||||
| **URI versioning** | `/v1/vehicles`, `/v2/vehicles` | Explicit, cacheable, easy to route. Pollutes paths. |
|
||||
| **Header versioning** | `Accept: application/vnd.api.v2+json` | Clean URIs. Harder to test, less cache-friendly. |
|
||||
| **Query param** | `/vehicles?version=2` | Simple but considered poor practice for REST. |
|
||||
|
||||
URI versioning is the most common and is what Azure APIM handles well via routing rules.
|
||||
|
||||
## 4.3 Breaking vs Non-Breaking Changes
|
||||
|
||||
Knowing what constitutes a breaking change is critical for API governance (i.e. why the API GC reviews spec PRs).
|
||||
|
||||
| **Non-breaking (additive)** | **Breaking** |
|
||||
| --------------------------------------- | ------------------------------------------------- |
|
||||
| Adding a new optional field to response | Removing or renaming a field |
|
||||
| Adding a new endpoint | Changing a field's type |
|
||||
| Adding a new optional query parameter | Making an optional parameter required |
|
||||
| New enum value (with caution) | Changing HTTP status codes for existing scenarios |
|
||||
| | Changing authentication schemes |
|
||||
|
||||
## 4.4 Resource Naming Conventions
|
||||
|
||||
- Use **nouns**, not verbs: `/journeys` not `/getJourneys`
|
||||
- Use **plural** for collections: `/vehicles` not `/vehicle`
|
||||
- Use **kebab-case** for multi-word: `/driver-events` not `/driverEvents`
|
||||
- Nest to show ownership, but limit depth: `/vehicles/{id}/journeys` is fine; `/vehicles/{id}/journeys/{jid}/events/{eid}/metadata` is not.
|
||||
- Never expose internal implementation details in paths (`/{internalDatabaseId}` leaks schema).
|
||||
|
||||
## 4.5 HTTP Status Codes
|
||||
|
||||
Correct status codes are part of the API contract. Misuse breaks consumers who rely on them.
|
||||
|
||||
| Code | Meaning | When to use |
|
||||
| ---- | --------------------- | -------------------------------------------------- |
|
||||
| 200 | OK | Successful GET, PUT, PATCH |
|
||||
| 201 | Created | Successful POST that created a resource |
|
||||
| 204 | No Content | Successful DELETE or action with no response body |
|
||||
| 400 | Bad Request | Client sent malformed/invalid data |
|
||||
| 401 | Unauthorized | Not authenticated (no or invalid token) |
|
||||
| 403 | Forbidden | Authenticated but not authorised for this resource |
|
||||
| 404 | Not Found | Resource does not exist |
|
||||
| 409 | Conflict | State conflict (duplicate, version mismatch) |
|
||||
| 422 | Unprocessable Entity | Semantically invalid (e.g. invalid date range) |
|
||||
| 429 | Too Many Requests | Rate limit exceeded |
|
||||
| 500 | Internal Server Error | Unhandled server-side failure |
|
||||
| 503 | Service Unavailable | Downstream dependency down, circuit breaker open |
|
||||
|
||||
# 5\. API Security Architecture
|
||||
|
||||
## 5.1 Authentication Patterns
|
||||
|
||||
| Pattern | How it works | Typical use |
|
||||
| ------------------ | ------------------------------------------------------------------ | ------------------------------------------ |
|
||||
| **API Keys** | Static key passed in header (`x-api-key`) or query param | Simple, internal/partner APIs |
|
||||
| **OAuth 2.0** | Token-based; client obtains a bearer token from auth server | Public APIs, delegated access |
|
||||
| **OpenID Connect** | OAuth 2.0 + identity layer (ID tokens, user info endpoint) | APIs that need to know **who** the user is |
|
||||
| **Mutual TLS** | Both client and server present certificates | High-security service-to-service |
|
||||
| **JWT** | Signed token carrying claims; verified without calling auth server | Stateless auth at gateway level |
|
||||
|
||||
Azure APIM supports all of these via policies. A common pattern: APIM validates the JWT at the gateway before the request ever reaches an OpenShift pod.
|
||||
|
||||
## 5.2 OAuth 2.0 Grant Types
|
||||
|
||||
| Grant type | Use case |
|
||||
| ----------------------------- | ------------------------------------------------------------ |
|
||||
| **Client Credentials** | Machine-to-machine (no user involved). Most common for APIs. |
|
||||
| **Authorization Code** | User-facing apps; user logs in and delegates access |
|
||||
| **Authorization Code + PKCE** | Same as above but for SPAs/mobile (no client secret) |
|
||||
| **Implicit** (deprecated) | Was used for SPAs - replaced by Auth Code + PKCE |
|
||||
|
||||
## 5.3 Zero Trust at the API Layer
|
||||
|
||||
Zero Trust means: **never trust, always verify** - even internal services must authenticate.
|
||||
|
||||
Principles applied to APIs:
|
||||
|
||||
- Every service-to-service call requires a valid token (no implicit trust on the internal network).
|
||||
- Tokens have minimum required scopes (principle of least privilege).
|
||||
- mTLS between internal services adds a second layer even if a token is compromised.
|
||||
- All traffic - internal and external - goes through the gateway and is logged.
|
||||
|
||||
# 6\. API Lifecycle Management
|
||||
|
||||
This maps directly to the APIOps workflow in the APIM notes.
|
||||
|
||||
``` mermaid
|
||||
flowchart LR
|
||||
Design[Design]
|
||||
Develop[Develop]
|
||||
Test[Test]
|
||||
Publish[Publish]
|
||||
Monitor[Monitor]
|
||||
Retire[Retire]
|
||||
|
||||
Design --> Develop --> Test --> Publish --> Monitor --> Retire
|
||||
|
||||
Design -.-> D1["OAS Spec\nContract First"]
|
||||
Develop -.-> D2["C# Project\nTemplates\nOpenShift"]
|
||||
Test -.-> D3["Gated Build\nPipeline\nLinting + API GC"]
|
||||
Publish -.-> D4["APIM Publish\nPipeline\nDev → Cert → Prod"]
|
||||
Monitor -.-> D5["Analytics\nDashboards\nAPIM Portal"]
|
||||
Retire -.-> D6["Deprecation\nNotices\nVersion Sunset"]
|
||||
```
|
||||
|
||||
## 6.1 API Governance
|
||||
|
||||
The API Governance Council (API GC) referenced in the notes is the enforcement body for architectural standards. Common governance concerns:
|
||||
|
||||
- **Linting**: Automated rules against the OAS spec. The APIOps pipeline uses scripts from `ApiManagement.Pipeline.AgentScripts` to enforce this.
|
||||
- **Review gates**: No spec change merges without GC approval - prevents inconsistent or insecure APIs reaching production.
|
||||
- **Naming standards**: Enforced in the spec review (see §4.4).
|
||||
- **Breaking change policy**: Defines how long old versions must be supported before retirement.
|
||||
- **Security policy**: All APIs must use approved auth methods; no unauthenticated endpoints in production.
|
||||
|
||||
## 6.2 APIOps (GitOps for APIs)
|
||||
|
||||
APIOps applies GitOps principles to API management: the APIM configuration is stored as code in a Git repository and the pipeline is the only mechanism that changes APIM state.
|
||||
|
||||
Key properties:
|
||||
|
||||
- **Declarative**: The `Microlise.APIOps` repo describes the desired state of all APIs in APIM.
|
||||
- **Versioned**: Every change is a PR - full audit trail.
|
||||
- **Automated**: The publish pipeline does the two-way sync; no manual APIM portal edits.
|
||||
- **Environment promotion**: Changes flow Dev -\> Cert -\> Prod, with a manual approval gate before Prod.
|
||||
|
||||
This is analogous to how Terraform or Helm work for infrastructure - the repo **is** the truth.
|
||||
|
||||
# 7\. API Observability
|
||||
|
||||
An often-overlooked architectural concern. APIs you can't observe are APIs you can't operate.
|
||||
|
||||
## 7.1 The Three Pillars
|
||||
|
||||
| Pillar | What it captures | Tooling examples |
|
||||
| ----------- | ----------------------------------------------------------- | ---------------------------------- |
|
||||
| **Logs** | Discrete events: requests, responses, errors, auth failures | Azure Monitor, ELK, Splunk |
|
||||
| **Metrics** | Aggregated numbers over time: latency, error rate, RPS | Prometheus, Azure Metrics, Grafana |
|
||||
| **Traces** | End-to-end request journey across services | Jaeger, Zipkin, Azure App Insights |
|
||||
|
||||
## 7.2 Key API Metrics to Track
|
||||
|
||||
- **Latency**: p50, p95, p99 - not just average. Averages hide outliers.
|
||||
- **Error rate**: 5xx rate (server errors) and 4xx rate (client errors) separately.
|
||||
- **Throughput**: Requests per second - used to set rate limits and plan capacity.
|
||||
- **Availability**: Uptime percentage. SLAs are usually defined here (99.9% = \~8.7h downtime/year).
|
||||
- **Quota consumption**: How much of a consumer's rate limit are they using?
|
||||
|
||||
Azure APIM exposes all of these natively and can emit them to Azure Monitor.
|
||||
|
||||
## 7.3 Correlation IDs
|
||||
|
||||
Every request should carry a unique `correlation-id` (or `x-request-id`) header. The gateway generates one if the client doesn't provide it and forwards it to all downstream services. This makes it possible to trace a single user request across multiple microservice logs.
|
||||
|
||||
``` mermaid
|
||||
flowchart LR
|
||||
C[Client]
|
||||
APIM["APIM\ngenerates correlation-id: abc-123"]
|
||||
SA["Service A logs\nabc-123 · vehicle lookup"]
|
||||
SB["Service B logs\nabc-123 · journey history"]
|
||||
|
||||
C --> APIM
|
||||
APIM --> SA
|
||||
SA --> SB
|
||||
```
|
||||
|
||||
# 8\. Microservices & API Design
|
||||
|
||||
The OpenShift deployment model in Microlise's stack implies microservices. API architecture must account for how services communicate internally vs. externally.
|
||||
|
||||
## 8.1 Internal vs External APIs
|
||||
|
||||
| Aspect | Internal (East-West) | External (North-South) |
|
||||
| --------------- | --------------------------------------- | ------------------------------------------ |
|
||||
| Consumers | Other microservices | Customers, partners, third parties |
|
||||
| Protocol | gRPC, internal REST, message queues | REST over HTTPS via APIM |
|
||||
| Auth | mTLS, service accounts, internal tokens | OAuth2, API keys managed by APIM |
|
||||
| Discoverability | Service mesh / internal DNS | Developer portal in APIM |
|
||||
| Governance | Team-level conventions | API GC, formal versioning, SLA commitments |
|
||||
|
||||
## 8.2 API Aggregation / BFF Pattern
|
||||
|
||||
Backend for Frontend (BFF): a dedicated API layer tailored to a specific consumer (e.g. a mobile app, a portal). Instead of the consumer calling 5 microservices, a BFF aggregates them into a single call.
|
||||
|
||||
``` mermaid
|
||||
flowchart LR
|
||||
MA[Mobile App]
|
||||
BFF[BFF: Mobile API]
|
||||
VS[Vehicle Service]
|
||||
JS[Journey Service]
|
||||
DS[Driver Service]
|
||||
|
||||
MA --> BFF
|
||||
BFF --> VS
|
||||
BFF --> JS
|
||||
BFF --> DS
|
||||
```
|
||||
|
||||
APIM policies can implement lightweight aggregation, but for complex cases a dedicated BFF service is cleaner.
|
||||
|
||||
## 8.3 Service Mesh (Complementary to API Gateway)
|
||||
|
||||
A service mesh (e.g. Istio, Linkerd) manages **internal** service-to-service communication within OpenShift/Kubernetes:
|
||||
|
||||
- mTLS between pods automatically.
|
||||
- Traffic policies (retries, circuit breaking) at the network level.
|
||||
- Observability (traces, metrics) without code changes.
|
||||
|
||||
The API Gateway handles North-South (external) traffic; the service mesh handles East-West (internal). They are complementary, not competing.
|
||||
|
||||
# 9\. API Design Patterns
|
||||
|
||||
## 9.1 Pagination
|
||||
|
||||
Never return unbounded collections. Standard patterns:
|
||||
|
||||
- **Offset/limit**: `GET /journeys?offset=0&limit=50`. Simple but inefficient at high offsets.
|
||||
- **Cursor-based**: `GET /journeys?cursor=eyJpZCI6MTAwfQ==`. Efficient for large datasets; the cursor encodes the last seen position.
|
||||
- **Page-based**: `GET /journeys?page=3&pageSize=50`. User-friendly but shares offset's inefficiency.
|
||||
|
||||
Response should include metadata:
|
||||
|
||||
``` json
|
||||
{
|
||||
"data": [...],
|
||||
"pagination": {
|
||||
"total": 1420,
|
||||
"limit": 50,
|
||||
"nextCursor": "eyJpZCI6MTUwfQ=="
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 9.2 Filtering, Sorting, and Field Selection
|
||||
|
||||
- Filtering: `GET /vehicles?status=active&driverType=HGV`
|
||||
- Sorting: `GET /journeys?sort=-startedAt` (prefix `-` for descending)
|
||||
- Field selection (sparse fieldsets): `GET /vehicles?fields=id,registration,status` - reduces payload size.
|
||||
|
||||
## 9.3 Idempotency
|
||||
|
||||
A request is idempotent if making it multiple times produces the same result as making it once. Crucial for retry logic.
|
||||
|
||||
| Method | Idempotent? | Safe (no side effects)? |
|
||||
| ------ | ----------- | ----------------------- |
|
||||
| GET | Yes | Yes |
|
||||
| PUT | Yes | No |
|
||||
| DELETE | Yes | No |
|
||||
| POST | No | No |
|
||||
| PATCH | No\* | No |
|
||||
|
||||
\*PATCH can be designed to be idempotent but isn't by definition.
|
||||
|
||||
For non-idempotent operations (POST), use an `Idempotency-Key` header. The server stores the result keyed to that value; duplicate requests return the cached result rather than processing again.
|
||||
|
||||
## 9.4 HATEOAS
|
||||
|
||||
Hypermedia as the Engine of Application State - responses include links to related actions:
|
||||
|
||||
``` json
|
||||
{
|
||||
"id": "v-123",
|
||||
"registration": "AB12 CDE",
|
||||
"_links": {
|
||||
"self": { "href": "/vehicles/v-123" },
|
||||
"journeys": { "href": "/vehicles/v-123/journeys" },
|
||||
"driver": { "href": "/drivers/d-456" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rarely implemented fully in practice but worth understanding as the most complete expression of REST.
|
||||
|
||||
# 10\. OpenAPI Specification Deep Dive
|
||||
|
||||
Since OAS is central to the APIOps pipeline, understanding its structure is practical knowledge.
|
||||
|
||||
``` yaml
|
||||
openapi: "3.1.0"
|
||||
info:
|
||||
title: Vehicle Service API
|
||||
version: "2.0.0"
|
||||
description: Manages vehicle records for the Microlise platform.
|
||||
|
||||
servers:
|
||||
- url: https://api.microlise.com/v2
|
||||
description: Production
|
||||
|
||||
paths:
|
||||
/vehicles/{vehicleId}:
|
||||
get:
|
||||
summary: Get a vehicle by ID
|
||||
operationId: getVehicleById # Unique identifier used in code gen
|
||||
tags: [Vehicles]
|
||||
parameters:
|
||||
- name: vehicleId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Vehicle found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Vehicle"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
|
||||
components:
|
||||
schemas:
|
||||
Vehicle:
|
||||
type: object
|
||||
required: [id, registration]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
registration:
|
||||
type: string
|
||||
example: "AB12 CDE"
|
||||
status:
|
||||
type: string
|
||||
enum: [active, inactive, maintenance]
|
||||
|
||||
responses:
|
||||
NotFound:
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ProblemDetails"
|
||||
|
||||
securitySchemes:
|
||||
oauth2:
|
||||
type: oauth2
|
||||
flows:
|
||||
clientCredentials:
|
||||
tokenUrl: https://auth.microlise.com/oauth2/token
|
||||
scopes:
|
||||
vehicles:read: Read vehicle data
|
||||
vehicles:write: Create and update vehicles
|
||||
|
||||
security:
|
||||
- oauth2: [vehicles:read]
|
||||
```
|
||||
|
||||
Key OAS concepts:
|
||||
|
||||
- `operationId`: Used by code generators and APIM to reference operations in policies.
|
||||
- `$ref`: DRY principle - define schemas and responses once, reuse everywhere.
|
||||
- `components`: The library section - schemas, parameters, responses, security schemes.
|
||||
- `tags`: Grouping for the developer portal - consumers see organised API docs.
|
||||
- `security`: Applied globally here; can be overridden per-operation.
|
||||
|
||||
# 11\. Connecting the Dots: Microlise Architecture Map
|
||||
|
||||
Mapping the APIM notes to the architectural concepts above:
|
||||
|
||||
| APIM Note Item | Architectural Concept |
|
||||
| ---------------------------------------- | -------------------------------------------------- |
|
||||
| Separate layer between customers & APIs | API Gateway Pattern (§3) |
|
||||
| OpenAPI spec / swagger build | Contract-First Design (§4.1), OAS (§10) |
|
||||
| APIOps pipeline, spec in git | APIOps / GitOps for APIs (§6.2) |
|
||||
| API Governance Council review | API Governance (§6.1), Breaking Changes (§4.3) |
|
||||
| Linting scripts (`AgentScripts`) | Automated governance enforcement |
|
||||
| Gated + main pipeline | CI/CD gates for quality and security |
|
||||
| Two-way sync, publish pipeline | Declarative state management (APIOps) |
|
||||
| Dev -\> Cert -\> Prod with approval gate | Environment promotion pattern (§6.2) |
|
||||
| Gen cluster vs Prod cluster | Environment isolation, blast radius reduction |
|
||||
| Reverse proxy pipeline | Reverse Proxy vs API Gateway (§3.2) |
|
||||
| Quay registry, OpenShift containers | Microservices deployment, East-West traffic (§8.1) |
|
||||
| Swagger/OAS spec as PR artefact | Spec-as-code, version-controlled contracts |
|
||||
|
||||
# 12\. Further Reading & Reference
|
||||
|
||||
## Recommended (from APIM notes)
|
||||
|
||||
- Quick Start Kubernetes - Nigel Poulton ([OpenShift vs K8s](https://microliseuk.sharepoint.com/sites/StorageCompute/ContainerPlatformUsers/SitePages/How-is-OpenShift-different-from-Kubernetes.aspx))
|
||||
|
||||
## Additional Architecture Resources
|
||||
|
||||
- [OpenAPI Specification 3.1.0 (official)](https://spec.openapis.org/oas/v3.1.0)
|
||||
- [AsyncAPI Documentation](https://www.asyncapi.com/docs)
|
||||
- [gRPC Official Docs](https://grpc.io/docs/)
|
||||
- [Azure API Management Docs](https://learn.microsoft.com/en-us/azure/api-management/)
|
||||
- [Microservices.io - API Gateway Pattern](https://microservices.io/patterns/apigateway.html)
|
||||
- [OAuth 2.0 (oauth.net)](https://oauth.net/2/)
|
||||
- [Swagger / OAS Reference](https://swagger.io/specification/)
|
||||
|
||||
## Key Terms Glossary
|
||||
|
||||
| Term | Definition |
|
||||
| --------------- | ---------------------------------------------------------------------------- |
|
||||
| OAS / Swagger | OpenAPI Specification - a standard format for describing REST APIs |
|
||||
| APIOps | Applying GitOps principles to API management (spec-as-code, pipeline-driven) |
|
||||
| APIM | API Management - the platform/layer that governs API lifecycle |
|
||||
| Gateway | Intermediary that enforces policy (auth, rate limiting, routing) for APIs |
|
||||
| Spec | Short for specification - the OAS JSON/YAML document describing an API |
|
||||
| Idempotency | Property where repeating a request has the same effect as making it once |
|
||||
| mTLS | Mutual TLS - both parties in a connection authenticate with certificates |
|
||||
| BFF | Backend for Frontend - an API tailored to a specific consumer's needs |
|
||||
| Service Mesh | Infrastructure layer managing internal service-to-service communication |
|
||||
| Breaking Change | An API change that requires existing consumers to update their integration |
|
||||
8
Career/API/ASP.NET Core Web API Fundamental Notes.md
Executable file
8
Career/API/ASP.NET Core Web API Fundamental Notes.md
Executable file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
note type:
|
||||
- note
|
||||
- api
|
||||
date: 2026-06-03
|
||||
done:
|
||||
---
|
||||
****Notes from [Pluralsight](https://app.pluralsight.com/ilx/video-courses/asp-dot-net-core-6-web-api-fundamentals/resources)****
|
||||
303
Career/API/Restful API.md
Executable file
303
Career/API/Restful API.md
Executable file
@@ -0,0 +1,303 @@
|
||||
---
|
||||
note type:
|
||||
- api
|
||||
- note
|
||||
date: 2026-06-03
|
||||
done: true
|
||||
---
|
||||
# What is a RESTful API?
|
||||
|
||||
A **RESTful API** is a web service that follows the principles of **REST (Representational State Transfer)**. REST is an architectural style used for designing networked applications.
|
||||
|
||||
In a RESTful system:
|
||||
|
||||
- Everything is treated as a **resource**
|
||||
- Resources are identified using **URLs**
|
||||
- Standard **HTTP methods** are used to interact with resources
|
||||
- Communication is usually done using **JSON**
|
||||
|
||||
Example resource:
|
||||
|
||||
/users
|
||||
/users/1
|
||||
/users/1/orders
|
||||
|
||||
These represent data stored on the server.
|
||||
|
||||
# Core HTTP Methods
|
||||
|
||||
REST APIs rely heavily on HTTP verbs.
|
||||
|
||||
| Method | Purpose | Example Endpoint |
|
||||
| ------ | --------------------------- | ---------------- |
|
||||
| GET | Retrieve data | GET /users |
|
||||
| POST | Create a new resource | POST /users |
|
||||
| PUT | Update an existing resource | PUT /users/1 |
|
||||
| DELETE | Remove a resource | DELETE /users/1 |
|
||||
|
||||
# Example Resource: User
|
||||
|
||||
Assume we have a simple **User** resource:
|
||||
|
||||
``` json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Alice",
|
||||
"email": "alice@email.com"
|
||||
}
|
||||
```
|
||||
|
||||
The API allows clients to create, read, update, and delete users.
|
||||
|
||||
# Creating a REST API in C\# (ASP.NET Core)
|
||||
|
||||
In C\#, REST APIs are commonly built using **ASP.NET Core Web API**.
|
||||
|
||||
Example project creation:
|
||||
|
||||
``` bash
|
||||
dotnet new webapi -n UserApi
|
||||
cd UserApi
|
||||
dotnet run
|
||||
```
|
||||
|
||||
This creates a ready-to-run REST API project.
|
||||
|
||||
# Defining a Model
|
||||
|
||||
First, define the resource model.
|
||||
|
||||
File: Models/User.cs
|
||||
|
||||
``` csharp
|
||||
namespace UserApi.Models
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This represents the data stored and returned by the API.
|
||||
|
||||
# Creating a Controller
|
||||
|
||||
Controllers handle HTTP requests.
|
||||
|
||||
File: Controllers/UserController.cs
|
||||
|
||||
``` csharp
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using UserApi.Models;
|
||||
|
||||
namespace UserApi.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private static List<User> users = new List<User>()
|
||||
{
|
||||
new User { Id = 1, Name = "Alice", Email = "alice@email.com" },
|
||||
new User { Id = 2, Name = "Bob", Email = "bob@email.com" }
|
||||
};
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<List<User>> GetUsers()
|
||||
{
|
||||
return Ok(users);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Endpoint created:
|
||||
|
||||
GET /api/user
|
||||
|
||||
Response:
|
||||
|
||||
``` json
|
||||
[
|
||||
{ "id": 1, "name": "Alice", "email": "alice@email.com" },
|
||||
{ "id": 2, "name": "Bob", "email": "bob@email.com" }
|
||||
]
|
||||
```
|
||||
|
||||
# Getting a Single Resource
|
||||
|
||||
Add an endpoint to retrieve a specific user.
|
||||
|
||||
``` csharp
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult<User> GetUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return Ok(user);
|
||||
}
|
||||
```
|
||||
|
||||
Endpoint:
|
||||
|
||||
GET /api/user/1
|
||||
|
||||
# Creating a Resource (POST)
|
||||
|
||||
Clients send JSON data to create a new user.
|
||||
|
||||
``` csharp
|
||||
[HttpPost]
|
||||
public ActionResult<User> CreateUser(User newUser)
|
||||
{
|
||||
newUser.Id = users.Max(u => u.Id) + 1;
|
||||
users.Add(newUser);
|
||||
|
||||
return CreatedAtAction(nameof(GetUser), new { id = newUser.Id }, newUser);
|
||||
}
|
||||
```
|
||||
|
||||
Example request:
|
||||
|
||||
``` json
|
||||
POST /api/user
|
||||
|
||||
{
|
||||
"name": "Charlie",
|
||||
"email": "charlie@email.com"
|
||||
}
|
||||
```
|
||||
|
||||
# Updating a Resource (PUT)
|
||||
|
||||
``` csharp
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult UpdateUser(int id, User updatedUser)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
user.Name = updatedUser.Name;
|
||||
user.Email = updatedUser.Email;
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
```
|
||||
|
||||
Endpoint:
|
||||
|
||||
PUT /api/user/1
|
||||
|
||||
# Deleting a Resource
|
||||
|
||||
``` csharp
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult DeleteUser(int id)
|
||||
{
|
||||
var user = users.FirstOrDefault(u => u.Id == id);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
users.Remove(user);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
```
|
||||
|
||||
Endpoint:
|
||||
|
||||
DELETE /api/user/1
|
||||
|
||||
# REST Principles
|
||||
|
||||
A good REST API should follow these key ideas:
|
||||
|
||||
## 1\. Statelessness
|
||||
|
||||
Each request contains all information needed.
|
||||
|
||||
The server does **not store client session state**.
|
||||
|
||||
## 2\. Resource-Based URLs
|
||||
|
||||
Endpoints should represent **nouns**, not verbs.
|
||||
|
||||
Good:
|
||||
|
||||
GET /users
|
||||
POST /users
|
||||
GET /users/1
|
||||
|
||||
Bad:
|
||||
|
||||
GET /getUsers
|
||||
POST /createUser
|
||||
|
||||
## 3\. Standard HTTP Status Codes
|
||||
|
||||
| Code | Meaning |
|
||||
| ---- | ------------ |
|
||||
| 200 | OK |
|
||||
| 201 | Created |
|
||||
| 204 | No Content |
|
||||
| 400 | Bad Request |
|
||||
| 404 | Not Found |
|
||||
| 500 | Server Error |
|
||||
|
||||
# Example Full API Structure
|
||||
|
||||
UserApi/
|
||||
├── Controllers/
|
||||
│ └── UserController.cs
|
||||
├── Models/
|
||||
│ └── User.cs
|
||||
├── Program.cs
|
||||
└── appsettings.json
|
||||
|
||||
# Testing the API
|
||||
|
||||
You can test APIs using tools like:
|
||||
|
||||
- curl
|
||||
- Postman
|
||||
- Swagger UI (included with ASP.NET)
|
||||
|
||||
Example curl request:
|
||||
|
||||
``` bash
|
||||
curl http://localhost:5000/api/user
|
||||
```
|
||||
|
||||
# Summary
|
||||
|
||||
A RESTful API:
|
||||
|
||||
- Exposes **resources via URLs**
|
||||
- Uses **HTTP methods (GET, POST, PUT, DELETE)**
|
||||
- Communicates typically using **JSON**
|
||||
- Is **stateless**
|
||||
- Returns **standard HTTP status codes**
|
||||
|
||||
In C\#, **ASP.NET Core Web API** makes building REST APIs straightforward using:
|
||||
|
||||
- Models
|
||||
- Controllers
|
||||
- Routing
|
||||
- Built-in JSON serialization
|
||||
Reference in New Issue
Block a user