mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
feat(api): document the client geolocation route in OpenAPI (#1617)
This commit is contained in:
1 parent
fca5f63b9e
commit
4e9b8fa1a6
3 files changed
+159
-11
No files matched your search
@@ -1,24 +1,40 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {GeolocationResponse} from '@fluxer/schema/src/domains/geolocation/GeolocationSchemas';
|
||||
import {resolveClientGeoip} from '@pkgs/geoip/src/ResolveClientGeoip';
|
||||
import type {Hono} from 'hono';
|
||||
import {Config} from '../Config';
|
||||
import {RateLimitMiddleware} from '../middleware/RateLimitMiddleware';
|
||||
import {OpenAPI} from '../middleware/ResponseTypeMiddleware';
|
||||
import {RateLimitConfigs} from '../RateLimitConfig';
|
||||
import type {HonoEnv} from '../types/HonoEnv';
|
||||
|
||||
export function GeolocationController(app: Hono<HonoEnv>): void {
|
||||
app.get('/ip', RateLimitMiddleware(RateLimitConfigs.IP_GEO_LOOKUP), async (ctx) => {
|
||||
ctx.header('Access-Control-Allow-Origin', '*');
|
||||
ctx.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
ctx.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
|
||||
const response = await resolveClientGeoip(ctx.req.raw, {
|
||||
maxmindDbPath: Config.geoip.maxmindDbPath,
|
||||
trustClientIpHeader: Config.proxy.trust_client_ip_header,
|
||||
clientIpHeaderName: Config.proxy.client_ip_header,
|
||||
});
|
||||
return ctx.json(response);
|
||||
});
|
||||
app.get(
|
||||
'/ip',
|
||||
RateLimitMiddleware(RateLimitConfigs.IP_GEO_LOOKUP),
|
||||
OpenAPI({
|
||||
operationId: 'get_client_geolocation',
|
||||
summary: 'Get client geolocation',
|
||||
responseSchema: GeolocationResponse,
|
||||
statusCode: 200,
|
||||
security: [],
|
||||
tags: ['Geolocation'],
|
||||
description:
|
||||
'Resolves the approximate location of the requesting client from its IP address, together with the locations where age restricted content is gated or unavailable.',
|
||||
}),
|
||||
async (ctx) => {
|
||||
ctx.header('Access-Control-Allow-Origin', '*');
|
||||
ctx.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
ctx.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
|
||||
const response = await resolveClientGeoip(ctx.req.raw, {
|
||||
maxmindDbPath: Config.geoip.maxmindDbPath,
|
||||
trustClientIpHeader: Config.proxy.trust_client_ip_header,
|
||||
clientIpHeaderName: Config.proxy.client_ip_header,
|
||||
});
|
||||
return ctx.json(response);
|
||||
},
|
||||
);
|
||||
app.options('/ip', (ctx) => {
|
||||
ctx.header('Access-Control-Allow-Origin', '*');
|
||||
ctx.header('Access-Control-Allow-Headers', 'Content-Type');
|
||||
|
||||
@@ -10800,6 +10800,64 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/ip": {
|
||||
"get": {
|
||||
"operationId": "get_client_geolocation",
|
||||
"summary": "Get client geolocation",
|
||||
"tags": ["Geolocation"],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/GeolocationResponse"}}}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request - The request was malformed or contained invalid data",
|
||||
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too Many Requests - You are being rate limited",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {"type": "string", "enum": ["RATE_LIMITED"]},
|
||||
"message": {"type": "string"},
|
||||
"retry_after": {"type": "number", "description": "Seconds to wait before retrying"},
|
||||
"global": {"type": "boolean", "description": "Whether this is a global rate limit"}
|
||||
},
|
||||
"required": ["code", "message", "retry_after"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Retry-After": {
|
||||
"description": "Number of seconds to wait before retrying (only on 429)",
|
||||
"schema": {"type": "integer"}
|
||||
},
|
||||
"X-RateLimit-Limit": {
|
||||
"description": "The number of requests that can be made in the current window",
|
||||
"schema": {"type": "integer"}
|
||||
},
|
||||
"X-RateLimit-Remaining": {
|
||||
"description": "The number of remaining requests that can be made",
|
||||
"schema": {"type": "integer"}
|
||||
},
|
||||
"X-RateLimit-Reset": {
|
||||
"description": "Unix timestamp when the rate limit resets",
|
||||
"schema": {"type": "integer"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error - An unexpected error occurred",
|
||||
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}
|
||||
}
|
||||
},
|
||||
"x-mint": {"metadata": {"title": "Get client geolocation"}},
|
||||
"description": "Resolves the approximate location of the requesting client from its IP address, together with the locations where age restricted content is gated or unavailable."
|
||||
}
|
||||
},
|
||||
"/oauth2/@me": {
|
||||
"get": {
|
||||
"operationId": "get_current_user_oauth2",
|
||||
@@ -31926,6 +31984,49 @@
|
||||
},
|
||||
"required": ["code", "type", "pack", "temporary"]
|
||||
},
|
||||
"GeolocationResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"countryCode": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "ISO 3166-1 alpha-2 country code resolved for the client, or null when it cannot be resolved"
|
||||
},
|
||||
"regionCode": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "ISO 3166-2 subdivision code resolved for the client, or null when it cannot be resolved"
|
||||
},
|
||||
"latitude": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Approximate latitude of the client, or null when it cannot be resolved"
|
||||
},
|
||||
"longitude": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Approximate longitude of the client, or null when it cannot be resolved"
|
||||
},
|
||||
"ageRestrictedGeos": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/GeoEntry"},
|
||||
"description": "Locations where age restricted content requires an age check"
|
||||
},
|
||||
"ageBlockedGeos": {
|
||||
"type": "array",
|
||||
"items": {"$ref": "#/components/schemas/GeoEntry"},
|
||||
"description": "Locations where age restricted content is unavailable"
|
||||
}
|
||||
},
|
||||
"required": ["countryCode", "regionCode", "latitude", "longitude", "ageRestrictedGeos", "ageBlockedGeos"]
|
||||
},
|
||||
"GeoEntry": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"countryCode": {"type": "string", "description": "ISO 3166-1 alpha-2 country code"},
|
||||
"regionCode": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "ISO 3166-2 subdivision code, or null when the entry covers the whole country"
|
||||
}
|
||||
},
|
||||
"required": ["countryCode", "regionCode"]
|
||||
},
|
||||
"OAuth2MeResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -38163,6 +38264,7 @@
|
||||
{"name": "Connections"},
|
||||
{"name": "Messages"},
|
||||
{"name": "Donations"},
|
||||
{"name": "Geolocation"},
|
||||
{"name": "Discovery"},
|
||||
{"name": "Emojis"},
|
||||
{"name": "Stickers"},
|
||||
|
||||
Reference in new issue
Block a user