proxy-pool/api/openapi/proxy-pool.yaml

423 lines
12 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openapi: 3.1.0
info:
title: Proxy Pool HTTP API
version: 1.0.0
description: |
Distribution API performs one-time exclusive extraction. A successful
Redis operation atomically removes or marks every returned proxy as
extracted in the TTL activity pool. Proxy details and per-extraction
records are not persisted in PostgreSQL. There is no release, renew, or
lease API. An authenticated credential may be limited to the fixed
`distribution:extract` permission; legacy credentials without configured
permissions retain full access. Credential client policy may further bound
a request's count, upstreams, and regions before Redis extraction.
servers:
- url: http://127.0.0.1:8081
description: Distribution API
tags:
- name: Distribution
description: 一次性独占提取上游代理的受保护接口。
- name: Health
description: Distribution 监听器的存活与就绪探针。
paths:
/api/v1/proxies/extract:
post:
tags: [Distribution]
operationId: extractProxies
summary: 一次性独占提取代理
description: |
需要 `distribution:extract`。
服务端通过单个 Redis 原子操作完成筛选、TTL/所有权复核、Gateway 预留、
从可分配池移除所选条目和短期幂等结果写入,再返回代理。相同代理不会
返回给两个成功请求,提取路径不访问 PostgreSQL。
`partial` 允许实际返回数量小于请求数量;`allOrNothing` 数量不足时不
提取任何代理并返回 409。未传 `fulfillment` 时使用服务端配置,默认
为 `partial`。`Idempotency-Key` 在 Redis 的有界 TTL 窗口内避免客户端因
响应丢失重试而再次消耗库存。命中凭据的 Client policy 可以额外限制
count、allowedUpstreams 和 regions越过该边界返回 403未调用 Redis。
security:
- ApiKeyAuth: []
- BasicAuth: []
- BearerAuth: []
- {}
parameters:
- $ref: '#/components/parameters/RequestID'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractRequest'
examples:
partial:
value:
count: 5
fulfillment: partial
filters:
protocols: [http]
regions: [shanghai]
allOrNothing:
value:
count: 10
fulfillment: allOrNothing
filters:
allowedUpstreams: [provider-a, provider-b]
responses:
'200':
description: Redis 原子提取已提交;返回的代理已退出当前可分配池
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/json:
schema:
$ref: '#/components/schemas/ExtractResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'409':
description: allOrNothing 模式下符合条件的库存不足,未提取任何代理
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
example:
type: https://proxy-pool.local/problems/insufficient-proxies
title: Insufficient proxies
status: 409
code: INSUFFICIENT_PROXIES
detail: requested 10 proxies but only 6 are currently eligible
requestId: req_01J4EXAMPLE
'422':
$ref: '#/components/responses/UnprocessableEntity'
'413':
$ref: '#/components/responses/RequestEntityTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'429':
$ref: '#/components/responses/TooManyRequests'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'500':
$ref: '#/components/responses/InternalServerError'
/health/live:
get:
tags: [Health]
operationId: getLiveness
summary: 进程存活探针
security: []
responses:
'200':
description: 进程存活
content:
application/json:
schema:
$ref: '#/components/schemas/Health'
/health/ready:
get:
tags: [Health]
operationId: getReadiness
summary: Distribution 就绪探针
description: Redis TTL 活动池不可用或无法保证原子提取时返回 503。
security: []
responses:
'200':
description: 可接受提取请求
content:
application/json:
schema:
$ref: '#/components/schemas/Health'
'503':
$ref: '#/components/responses/ServiceUnavailable'
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
BasicAuth:
type: http
scheme: basic
BearerAuth:
type: http
scheme: bearer
parameters:
RequestID:
name: X-Request-ID
in: header
required: false
description: 调用方请求标识;缺省时由服务端生成。
schema:
type: string
maxLength: 128
IdempotencyKey:
name: Idempotency-Key
in: header
required: false
description: |
同一客户端在幂等记录保留期内重用该键会得到首次提交结果,不会再次
提取。未认证客户端默认以可信代理链解析后的规范化来源 IP 标识。
建议所有会自动重试的客户端提供。
schema:
type: string
minLength: 8
maxLength: 128
headers:
RequestID:
description: 服务端最终使用的请求标识。
schema:
type: string
schemas:
ExtractRequest:
type: object
additionalProperties: false
required: [count]
properties:
count:
type: integer
minimum: 1
maximum: 1000
description: 仍受服务端 maxCountPerRequest 限制。
fulfillment:
type: string
enum: [partial, allOrNothing]
description: 缺省时使用服务端配置;默认 partial。
filters:
$ref: '#/components/schemas/ExtractFilters'
ExtractFilters:
type: object
additionalProperties: false
properties:
protocols:
type: array
maxItems: 64
uniqueItems: true
items:
type: string
enum: [http, https, socks5]
regions:
type: array
maxItems: 64
uniqueItems: true
items:
type: string
carriers:
type: array
maxItems: 64
uniqueItems: true
items:
type: string
allowedUpstreams:
type: array
maxItems: 64
uniqueItems: true
items:
type: string
ExtractResponse:
type: object
additionalProperties: false
required: [requestId, requested, returned, proxies]
properties:
requestId:
type: string
requested:
type: integer
minimum: 1
returned:
type: integer
minimum: 0
proxies:
type: array
items:
$ref: '#/components/schemas/ExtractedProxy'
ExtractedProxy:
type: object
additionalProperties: false
required:
- id
- protocol
- host
- port
- url
- upstream
- expiresAt
- remainingTtlSeconds
- extractedAt
properties:
id:
type: string
example: px_01J4EXAMPLE
protocol:
type: string
enum: [http, https, socks5]
host:
type: string
example: 192.0.2.10
port:
type: integer
minimum: 1
maximum: 65535
username:
type: string
password:
type: string
format: password
description: 真实代理凭据,只出现在提取成功响应中。
url:
type: string
format: uri
description: 含真实代理凭据的连接 URL必须按敏感数据处理。
example: http://USER:PASSWORD@192.0.2.10:8080
region:
type: string
carrier:
type: string
upstream:
type: string
expiresAt:
type: string
format: date-time
remainingTtlSeconds:
type: integer
minimum: 0
extractedAt:
type: string
format: date-time
Health:
type: object
additionalProperties: false
required: [status]
properties:
status:
type: string
enum: [ok, degraded]
version:
type: string
configVersion:
type: string
Problem:
type: object
additionalProperties: true
required: [type, title, status, code]
properties:
type:
type: string
format: uri
title:
type: string
status:
type: integer
code:
type: string
detail:
type: string
requestId:
type: string
invalidParams:
type: array
items:
type: object
required: [name, reason]
properties:
name:
type: string
reason:
type: string
responses:
BadRequest:
description: 请求体、Header 或 JSON 格式无效
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
Unauthorized:
description: 所配置的认证方法未通过
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
WWW-Authenticate:
schema:
type: string
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
Forbidden:
description: 来源访问控制或客户端权限拒绝
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
UnprocessableEntity:
description: 参数语法有效但违反业务约束
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
TooManyRequests:
description: 超过全局或客户端速率限制
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
Retry-After:
schema:
type: integer
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
ServiceUnavailable:
description: Redis TTL 活动池不可用、原子提取不可执行或服务正在排空
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
RequestEntityTooLarge:
description: 请求体超过服务端限制
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
UnsupportedMediaType:
description: Content-Type 不是 application/json
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
InternalServerError:
description: 未分类的服务端错误
headers:
X-Request-ID:
$ref: '#/components/headers/RequestID'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'