mirror of
git://f0xx.org/ac/ac-ms-url-shortener
synced 2026-07-29 01:19:38 +03:00
254 lines
6.0 KiB
YAML
254 lines
6.0 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: Android Cast URL Shortener
|
|
description: |
|
|
Standalone service at https://s.f0xx.org — SPEC docs/specs/20100611_3_url_shortener.md
|
|
version: 0.1.0
|
|
servers:
|
|
- url: https://s.f0xx.org
|
|
description: Production (FE TLS → BE :80)
|
|
|
|
paths:
|
|
/api/v1/health:
|
|
get:
|
|
summary: Service health
|
|
operationId: health
|
|
responses:
|
|
'200':
|
|
description: OK
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
service:
|
|
type: string
|
|
|
|
/api/v1/shorten:
|
|
get:
|
|
summary: Shorten URL (query params)
|
|
description: Prefer POST for long URLs or sensitive query strings.
|
|
operationId: shortenGet
|
|
parameters:
|
|
- $ref: '#/components/parameters/url'
|
|
- $ref: '#/components/parameters/bearer'
|
|
- $ref: '#/components/parameters/signer'
|
|
- $ref: '#/components/parameters/ttl'
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/ShortenSuccess'
|
|
'400':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'401':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'403':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'409':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'429':
|
|
$ref: '#/components/responses/ShortenError'
|
|
post:
|
|
summary: Shorten URL (JSON body) — preferred
|
|
operationId: shortenPost
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ShortenRequest'
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/ShortenSuccess'
|
|
'400':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'401':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'403':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'409':
|
|
$ref: '#/components/responses/ShortenError'
|
|
'429':
|
|
$ref: '#/components/responses/ShortenError'
|
|
|
|
/api/v1/qr/{slug}.png:
|
|
get:
|
|
summary: QR code PNG for short URL
|
|
operationId: qrPng
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
pattern: '^[a-f0-9]{6,16}$'
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 256
|
|
minimum: 128
|
|
maximum: 512
|
|
responses:
|
|
'200':
|
|
description: PNG image
|
|
content:
|
|
image/png:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
'404':
|
|
description: Unknown slug
|
|
'410':
|
|
description: Expired slug
|
|
|
|
/{slug}:
|
|
get:
|
|
summary: Redirect to original URL
|
|
operationId: redirect
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
pattern: '^[a-f0-9]{6,16}$'
|
|
responses:
|
|
'302':
|
|
description: Found — Location is original URL
|
|
headers:
|
|
Location:
|
|
schema:
|
|
type: string
|
|
format: uri
|
|
'404':
|
|
description: Unknown slug
|
|
'410':
|
|
description: Expired slug
|
|
head:
|
|
summary: Redirect probe (no body)
|
|
operationId: redirectHead
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'302':
|
|
description: Found
|
|
'404':
|
|
description: Unknown
|
|
'410':
|
|
description: Expired
|
|
|
|
components:
|
|
parameters:
|
|
url:
|
|
name: url
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
format: uri
|
|
maxLength: 2048
|
|
bearer:
|
|
name: bearer
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
minLength: 8
|
|
signer:
|
|
name: signer
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
ttl:
|
|
name: ttl
|
|
in: query
|
|
required: false
|
|
description: Seconds until expiry; 0 = permanent (signer required)
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
default: 86400
|
|
|
|
schemas:
|
|
ShortenRequest:
|
|
type: object
|
|
required: [url, bearer]
|
|
properties:
|
|
url:
|
|
type: string
|
|
format: uri
|
|
maxLength: 2048
|
|
bearer:
|
|
type: string
|
|
signer:
|
|
type: string
|
|
ttl:
|
|
type: integer
|
|
minimum: 0
|
|
default: 86400
|
|
ShortenSuccess:
|
|
type: object
|
|
required: [code, url, u, bearer, ttl]
|
|
properties:
|
|
code:
|
|
type: string
|
|
enum: ['0']
|
|
url:
|
|
type: string
|
|
format: uri
|
|
u:
|
|
type: string
|
|
format: uri
|
|
description: Short URL
|
|
bearer:
|
|
type: string
|
|
ttl:
|
|
type: string
|
|
description: Remaining seconds as string; "0" if permanent
|
|
qr:
|
|
type: string
|
|
format: uri
|
|
description: Optional v1.1 — URL to QR PNG
|
|
ShortenError:
|
|
type: object
|
|
required: [code, desc]
|
|
properties:
|
|
code:
|
|
type: string
|
|
enum:
|
|
- ACCESS_DENIED
|
|
- MISSING_BEARER
|
|
- INVALID_URL
|
|
- TTL_EXPIRED
|
|
- SIGNER_REQUIRED
|
|
- RATE_LIMITED
|
|
- INTERNAL
|
|
- NOT_IMPLEMENTED
|
|
url:
|
|
type: string
|
|
bearer:
|
|
type: string
|
|
desc:
|
|
type: string
|
|
|
|
responses:
|
|
ShortenSuccess:
|
|
description: Short URL created or cached
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ShortenSuccess'
|
|
ShortenError:
|
|
description: Error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ShortenError'
|