From cec7f1566eeaa9569f3d9aafecd515dab09f7462 Mon Sep 17 00:00:00 2001 From: Abdussamet Kocak Date: Thu, 8 Oct 2026 21:29:07 +0200 Subject: [PATCH] feat(api): Add Swagger UI for v1 endpoints Serve interactive docs at /api, covering only the current /api/v1/* endpoints. Deprecated /api/diyanet/* endpoints are left undocumented. --- internal/api/api.go | 10 +++ internal/api/docs.go | 27 +++++++ internal/api/openapi.yaml | 156 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 internal/api/docs.go create mode 100644 internal/api/openapi.yaml diff --git a/internal/api/api.go b/internal/api/api.go index 6d304b0..7d3315a 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -261,6 +261,16 @@ func New(services Services) *fiber.App { return ctx.JSON(mapped) }) + app.Get("/api/openapi.yaml", func(ctx fiber.Ctx) error { + ctx.Response().Header.Set(fiber.HeaderContentType, "application/yaml") + return ctx.Send(openapiSpec) + }) + + app.Get("/api", func(ctx fiber.Ctx) error { + ctx.Response().Header.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8) + return ctx.SendString(swaggerHTML) + }) + app.Use("/", static.New("", static.Config{FS: templates.FS()})) return app diff --git a/internal/api/docs.go b/internal/api/docs.go new file mode 100644 index 0000000..47e2c3f --- /dev/null +++ b/internal/api/docs.go @@ -0,0 +1,27 @@ +package api + +import _ "embed" + +//go:embed openapi.yaml +var openapiSpec []byte + +const swaggerHTML = ` + + + + Prayer Times API + + + +
+ + + +` diff --git a/internal/api/openapi.yaml b/internal/api/openapi.yaml new file mode 100644 index 0000000..dc256a9 --- /dev/null +++ b/internal/api/openapi.yaml @@ -0,0 +1,156 @@ +openapi: 3.0.3 +info: + title: Prayer Times API + version: "1" + description: Prayer times and location lookup, backed by Diyanet data. +externalDocs: + description: Source code + url: https://git.abdus.dev/abdus/prayertimes-go/ +servers: + - url: / +paths: + /api/v1/diyanet/location: + get: + summary: Search locations + description: Search locations by free-text query, or find the nearest location to a coordinate pair. + parameters: + - name: query + in: query + description: Free-text location search. Mutually exclusive with latitude/longitude. + schema: + type: string + - name: latitude + in: query + description: Required together with longitude when query is omitted. + schema: + type: number + format: double + - name: longitude + in: query + description: Required together with latitude when query is omitted. + schema: + type: number + format: double + responses: + "200": + description: Matching locations. + content: + application/json: + schema: + type: object + properties: + locations: + type: array + items: + $ref: "#/components/schemas/Location" + "400": + description: Missing both query and coordinates. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /api/v1/diyanet/prayertimes: + get: + summary: Get prayer times + description: Get prayer times by location ID, or by coordinates. + parameters: + - name: location_id + in: query + description: Mutually exclusive with latitude/longitude. + schema: + type: string + - name: latitude + in: query + schema: + type: number + format: double + - name: longitude + in: query + schema: + type: number + format: double + - name: utc + in: query + description: Return timestamps in UTC instead of the location's local timezone. + schema: + type: boolean + default: false + responses: + "200": + description: Prayer times for the resolved location. + content: + application/json: + schema: + type: object + properties: + location: + $ref: "#/components/schemas/Location" + prayertimes: + type: array + items: + $ref: "#/components/schemas/PrayerTimes" + "400": + description: Missing both location_id and coordinates. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "422": + description: Invalid location. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + +components: + schemas: + Location: + type: object + properties: + id: + type: integer + name: + type: string + ascii_name: + type: string + alternate_names: + type: string + country_code: + type: string + latitude: + type: number + format: double + longitude: + type: number + format: double + timezone: + type: string + PrayerTimes: + type: object + properties: + date: + type: string + format: date + date_hijri: + type: string + fajr: + type: string + example: "05:47" + sunrise: + type: string + dhuhr: + type: string + asr: + type: string + sunset: + type: string + maghrib: + type: string + isha: + type: string + Error: + type: object + properties: + message: + type: string