Repository navigation
Request Lifecycle
本页描述一个 HTTP 请求从进入 SPACK 到返回响应的完整路径。
This page describes how an HTTP request moves through SPACK from ingress to response.
sequenceDiagram
participant C as Client
participant S as Fiber server
participant P as Path cleaner
participant R as Prepared snapshot
participant V as Variant selector
participant D as Delivery
participant E as Event bus
participant M as Metrics
C->>S: GET /assets/app.js<br/>Accept-Encoding: br,zstd,gzip
S->>P: normalize mount and path
P-->>S: normalized asset key
S->>R: lookup response plan
R->>V: choose best variant
V-->>R: br/zstd/gzip/identity or image variant
R-->>S: prepared response plan
S->>D: deliver body or file
D-->>C: 200, 304, 206, or fallback response
S->>E: VariantServed / cache event
S->>M: request and delivery metrics
中文:HTTP 请求首先进入 Fiber route。SPACK 不实现复杂 location 语义,而是使用单一 asset mount。这样能把路由匹配保持在低成本路径。
English: The request first enters a Fiber route. SPACK does not implement complex location semantics. It uses one asset mount, which keeps route matching cheap.
关键行为:
-
/healthz,/livez,/readyz,/catalog,/robots.txt等内置端点先匹配。 - 资产请求进入 static asset route。
- debug runtime 在独立端口提供
/prometheus,/pprof,/debug/statsviz。
Key behavior:
- Built-in endpoints such as
/healthz,/livez,/readyz,/catalog, and/robots.txtare matched first. - Asset requests enter the static asset route.
- The debug runtime exposes
/prometheus,/pprof, and/debug/statsvizon a separate port.
flowchart LR
Raw["raw request path"] --> Mount["strip assets.path mount"]
Mount --> Decode["safe percent decoding"]
Decode --> Clean["clean traversal and slash shape"]
Clean --> Key["catalog asset key"]
中文:requestpath 负责处理 mount path、percent-encoded path、SPA-style route 和目录入口。已经规范的常见路径走 fast path。
English: requestpath handles mount paths, percent-encoded paths, SPA-style routes, and directory entries. Already-normalized common paths take a fast path.
中文:prepared snapshot 是一个不可变的响应计划集合,按 route/index 组织。请求命中 snapshot 后,不需要重新计算大部分 header、cache policy、resource hints 或 variant 信息。
English: The prepared snapshot is an immutable set of response plans organized by route/index. Once a request hits the snapshot, most headers, cache policy, resource hints, and variant information are already computed.
可能结果:
| Result | 行为 / Behavior |
|---|---|
| Direct hit | 返回源文件或 prepared body。Return source file or prepared body. |
| Encoding variant hit | 根据 Accept-Encoding 返回 br/zstd/gzip。Return br/zstd/gzip based on Accept-Encoding. |
| Image variant hit | 根据 query 或 Accept 返回图片变体。Return image variant based on query or Accept. |
| Fallback hit | 返回 assets.fallback.target。Return assets.fallback.target. |
| Miss | 返回 404 或触发 lazy generation。Return 404 or trigger lazy generation. |
客户端只有在请求头包含对应编码时才会收到压缩版本:
The client receives a compressed variant only when Accept-Encoding allows it:
Accept-Encoding: br,zstd,gzip
如果请求没有 Accept-Encoding,或者只有 identity,SPACK 返回 identity 版本。
If the request has no Accept-Encoding, or only allows identity, SPACK returns the identity version.
图片变体可以由 query 或 Accept 触发:
Image variants can be triggered by query parameters or the Accept header:
/assets/photo.jpg?w=640
/assets/photo.jpg?format=png
/assets/photo.jpg?w=640&format=jpeg
Accept: image/jpeg,image/png
SPACK 支持:
If-None-MatchIf-Modified-SinceHEAD- range request
SPACK supports:
If-None-MatchIf-Modified-SinceHEAD- range requests
flowchart TB
Request["request"] --> Validator["validator headers"]
Validator --> Match{"ETag or Last-Modified match?"}
Match -->|yes| NotModified["304 Not Modified"]
Match -->|no| Range{"Range request?"}
Range -->|yes| Partial["206 Partial Content"]
Range -->|no| Full["200 OK"]
| Delivery mode | 说明 / Description |
|---|---|
prepared in-memory body |
小文件预编译到 snapshot,适合极热路径。Small files embedded in snapshot for very hot paths. |
memory_cache_hit |
Ristretto hot asset cache 命中。Ristretto hot asset cache hit. |
memory_cache_fill |
读取后写入 memory cache。Read then fill memory cache. |
sendfile |
大文件或普通磁盘文件。Large files or normal disk-backed files. |
sendfile_range |
range request。Range request. |
响应后,SPACK 会记录指标并发送生命周期事件:
After response, SPACK records metrics and publishes lifecycle events:
- request duration
- delivery mode
- served variant
- cache hit or miss
- lazy generation request
- catalog or prepared snapshot rebuild triggers
事件不会阻塞核心响应路径。Event handling does not block the core response path.
flowchart LR
Request["GET /robots.txt"] --> Static{"static robots.txt exists?"}
Static -->|yes and override=false| ServeStatic["serve scanned file"]
Static -->|no or override=true| Enabled{"robots.enable?"}
Enabled -->|yes| Template["render embedded template"]
Enabled -->|no| NotFound["404"]
Template --> Response["text/plain response"]
中文:静态文件优先。如果没有静态文件,SPACK 才根据配置和 embed template 自动生成。
English: Static files take precedence. If no static file exists, SPACK generates one from config and an embedded template.