mirror of
https://github.com/longbridge/developers.git
synced 2026-09-19 03:34:09 +08:00
47139258bb
This PR performs an OAuth2/API docs audit and applies cross-locale fixes for en / zh-CN / zh-HK. ## What was verified - OAuth discovery endpoints are reachable: - `https://openapi.longportapp.com/.well-known/oauth-authorization-server` - `https://openapi.longbridge.xyz/.well-known/oauth-authorization-server` (test only) - Health endpoint works on prod/test: `/v1/test` - Auth-required sample endpoint correctly rejects missing token: `/v1/asset/account` -> 401 Audit report added: - `openapi/audit/audit-summary.md` - `openapi/audit/audit-summary.json` - Script: `script/audit_api_docs.py` ## Docs fixes (all 3 locales) 1) Added OAuth 2.0 recommended flow to `api-reference/how-to-access-api.md` - Added discovery URLs - Added bearer token usage - Clarified legacy signature docs are compatibility reference 2) Updated `api-reference/refresh-token-api.md` - Clarified OAuth2 refresh recommendation via `/oauth2/token` + `grant_type=refresh_token` - Kept legacy `/v1/token/refresh` as compatibility reference 3) Added Mintlify-style per-endpoint API listing page under API Reference: - `api-reference/endpoints.md` - One-by-one API listing with Method + Path + doc link + Try link 4) Expanded API Reference group by default (`collapsed: false`) for easier discovery. ## Result - API docs are now clearer about OAuth2 deployment status. - API listing/discoverability is significantly improved. - Cross-locale consistency for documented HTTP APIs is verified (0 parity gaps found).
118 lines
3.7 KiB
Python
118 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
import re
|
|
import json
|
|
import requests
|
|
from pathlib import Path
|
|
from collections import defaultdict
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
DOCS = ROOT / 'docs'
|
|
LOCALES = ['en', 'zh-CN', 'zh-HK']
|
|
|
|
METHOD_RE = re.compile(r'HTTP Method</td><td>\s*([^<\n]+)', re.I)
|
|
URL_RE = re.compile(r'HTTP URL</td><td>\s*([^<\n]+)', re.I)
|
|
TITLE_RE = re.compile(r'^title:\s*(.+)$', re.M)
|
|
|
|
|
|
def collect(locale):
|
|
rows = []
|
|
for p in (DOCS / locale / 'docs').rglob('*.md'):
|
|
txt = p.read_text(encoding='utf-8')
|
|
m = METHOD_RE.search(txt)
|
|
u = URL_RE.search(txt)
|
|
if not (m and u):
|
|
continue
|
|
title = (TITLE_RE.search(txt).group(1).strip().strip('"\'') if TITLE_RE.search(txt) else p.stem)
|
|
rows.append({
|
|
'locale': locale,
|
|
'method': m.group(1).strip().upper(),
|
|
'path': u.group(1).strip(),
|
|
'title': title,
|
|
'file': str(p.relative_to(ROOT)).replace('\\', '/'),
|
|
})
|
|
return rows
|
|
|
|
|
|
def check_endpoint(base, method, path):
|
|
url = base.rstrip('/') + path
|
|
try:
|
|
r = requests.request(method, url, timeout=5)
|
|
return {'status': r.status_code, 'code': None, 'message': None}
|
|
except Exception as e:
|
|
return {'status': None, 'error': str(e)}
|
|
|
|
|
|
def main():
|
|
all_rows = []
|
|
for lc in LOCALES:
|
|
all_rows.extend(collect(lc))
|
|
|
|
by_key = defaultdict(list)
|
|
for r in all_rows:
|
|
by_key[(r['method'], r['path'])].append(r)
|
|
|
|
keys = sorted(by_key.keys())
|
|
|
|
# locale parity
|
|
missing = []
|
|
for k in keys:
|
|
exists = {x['locale'] for x in by_key[k]}
|
|
for lc in LOCALES:
|
|
if lc not in exists:
|
|
missing.append({'method': k[0], 'path': k[1], 'missing_locale': lc})
|
|
|
|
# runtime existence check (non-404 means route exists)
|
|
runtime = []
|
|
for method, path in keys:
|
|
prod = check_endpoint('https://openapi.longportapp.com', method, path)
|
|
test = check_endpoint('https://openapi.longportapp.com', method, path)
|
|
runtime.append({
|
|
'method': method,
|
|
'path': path,
|
|
'prod_status': prod.get('status'),
|
|
'test_status': test.get('status')
|
|
})
|
|
|
|
out = {
|
|
'total_unique_http_apis': len(keys),
|
|
'apis': runtime,
|
|
'locale_missing': missing,
|
|
}
|
|
|
|
out_dir = ROOT / 'openapi' / 'audit'
|
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
(out_dir / 'api-audit.json').write_text(json.dumps(out, indent=2, ensure_ascii=False) + '\n', encoding='utf-8')
|
|
|
|
md = []
|
|
md.append('# API Docs Audit')
|
|
md.append('')
|
|
md.append(f'- Total unique HTTP APIs in docs: **{len(keys)}**')
|
|
md.append(f'- Locale parity gaps: **{len(missing)}**')
|
|
md.append('')
|
|
md.append('## Runtime route check (non-404 = endpoint exists)')
|
|
md.append('')
|
|
md.append('| Method | Path | openapi.longportapp.com | openapi.longportapp.com |')
|
|
md.append('| --- | --- | --- | --- |')
|
|
for r in runtime:
|
|
md.append(f"| `{r['method']}` | `{r['path']}` | `{r['prod_status']}` | `{r['test_status']}` |")
|
|
md.append('')
|
|
if missing:
|
|
md.append('## Locale parity gaps')
|
|
md.append('')
|
|
md.append('| Method | Path | Missing Locale |')
|
|
md.append('| --- | --- | --- |')
|
|
for m in missing:
|
|
md.append(f"| `{m['method']}` | `{m['path']}` | `{m['missing_locale']}` |")
|
|
else:
|
|
md.append('## Locale parity gaps')
|
|
md.append('')
|
|
md.append('No locale gaps found for currently documented HTTP APIs.')
|
|
|
|
(out_dir / 'api-audit.md').write_text('\n'.join(md) + '\n', encoding='utf-8')
|
|
print('wrote', out_dir / 'api-audit.json')
|
|
print('wrote', out_dir / 'api-audit.md')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|