1
Fork 0
mirror of https://github.com/Steffo99/distributed-arcade.git synced 2024-10-16 14:37:31 +00:00
distributed-arcade/docs/openapi.yaml

344 lines
11 KiB
YAML

openapi: 3.0.3
info:
title: "Distributed Arcade"
version: 0.3.1
description: |-
A super-fast high score gatherer using Rust and Redis.
It allows the creation of _boards_, [sorted sets](https://redis.io/docs/data-types/sorted-sets/) that can be used to track the scores of players in videogames.
It is written to be extremely fast and scalable: it should be able to receive bursts of many requests.
Errors can be distinguished from successful requests via HTTP status codes >=400.
contact:
name: "Stefano Pigozzi"
url: "https://www.steffo.eu"
email: "me@steffo.eu"
license:
name: "GNU Affero General Public License v3.0 or later"
url: https://github.com/Steffo99/distributed-arcade/blob/main/LICENSE.txt"
servers:
- url: "https://arcade.steffo.eu"
description: "Experimental production server"
- url: "http://127.0.0.1:30000"
description: "Local development server"
tags:
- name: "Home"
description: "Launch checklist"
- name: "Board"
description: "About boards"
- name: "Score"
description: "Submit scores"
paths:
/:
get:
operationId: "getHome"
summary: "Verify that the web server is working as expected"
description: |-
This method simply echoes back a response, and can be used to verify that the API web server is working.
tags: ["Home"]
responses:
204:
description: "Working as expected"
post:
operationId: "postHome"
summary: "Verify that everything is working as expected"
description: |-
This method is like `GET /`, but it also `PING`s the Redis server to ensure it is working and configured properly.
tags: ["Home"]
responses:
204:
description: "Working as expected"
500:
description: "Did not receive `PONG` from redis"
content:
application/json:
schema:
type: string
example: "Redis gave an unexpected response"
502:
$ref: "#/components/responses/RedisCmdFailed"
504:
$ref: "#/components/responses/RedisConnFailed"
/board/:
get:
operationId: "getBoard"
summary: "Get the scores of a board"
description: |-
This method requests a page of scores from a board using the [`ZSCAN`](https://redis.io/commands/zscan/) Redis command.
An offset must be specified to start returning scores from a certain index.
The number of responses to return must be specified as well.
tags: ["Board"]
parameters:
- $ref: "#/components/parameters/board"
- $ref: "#/components/parameters/offset"
- $ref: "#/components/parameters/size"
responses:
200:
description: "Scores retrieved successfully"
content:
application/json:
schema:
type: array
items:
type: object
description: "A score submitted by an user."
properties:
name:
type: string
description: "The name of the user who submitted the score."
example: "Steffo"
score:
type: number
description: "The submitted score."
example: 1234.56
502:
$ref: "#/components/responses/RedisCmdFailed"
504:
$ref: "#/components/responses/RedisConnFailed"
post:
operationId: "postBoard"
summary: "Create a new board"
description: |-
This method creates a new board.
It returns its _score submission token_ (`XBoardToken` in this spec), which is required to submit new scores to the board.
Boards can use two different orders:
- using the `Ascending` order, lower scores are better ranked than higher scores, like in racing games or golf;
- using the `Descending` order, higher scores are better ranked than lower scores, like in arcade games or athletics.
**WARNING: Once created, a board cannot be edited or deleted, and its token will not be accessible any longer!**
Requires an authorization key, set as the `CREATE_TOKEN` environment variable of the server.
tags: ["Board"]
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: "The name of the board to create. It will be converted to kebab-case."
example: "gravityfusion"
order:
type: string
example: "Descending"
description: "The ordering of the board, either ascending or descending."
enum:
- "Ascending"
- "Descending"
security:
- XCreateToken: []
responses:
201:
description: "Board created successfully"
content:
application/json:
schema:
type: string
example: "W4SbhbJ3tnGaIM1S"
links:
getScore:
operationId: "getScore"
parameters:
board: "$response.body/name"
putScore:
operationId: "putScore"
parameters:
board: "$response.body/name"
401:
description: "Missing, invalid or malformed Authorization header"
content:
application/json:
schema:
type: string
example: "Missing Authorization header"
403:
description: "Invalid create token"
content:
application/json:
schema:
type: string
example: "Invalid create token"
409:
description: "Board already exists"
content:
application/json:
schema:
type: string
example: "Board already exists"
500:
description: "Could not generate secure board token"
content:
application/json:
schema:
type: string
example: "Could not generate secure board token"
502:
$ref: "#/components/responses/RedisCmdFailed"
504:
$ref: "#/components/responses/RedisConnFailed"
/score/:
get:
operationId: "getScore"
summary: "Get a score from a board"
description: |-
Retrieve the score and the position that the given user has on the leaderboard.
tags: ["Score"]
parameters:
- $ref: "#/components/parameters/board"
- $ref: "#/components/parameters/player"
responses:
200:
description: "Score retrieved successfully"
content:
application/json:
schema:
type: object
properties:
score:
type: number
description: "The score of the specified player."
example: 1234.56
rank:
type: integer
description: "The zero-indexed rank of the specified player. (You may probably want to add `1` before displaying it to an user.)"
example: 0
502:
$ref: "#/components/responses/RedisCmdFailed"
504:
$ref: "#/components/responses/RedisConnFailed"
put:
operationId: "putScore"
summary: "Submit a score to a board"
tags: ["Score"]
parameters:
- $ref: "#/components/parameters/board"
- $ref: "#/components/parameters/player"
requestBody:
required: true
content:
application/json:
schema:
type: number
description: "The score to submit to the board."
example: 1234.56
security:
- XBoardToken: []
responses:
200:
description: "Score discarded as it was worse than the previous one"
content:
application/json:
schema:
type: object
properties:
score:
type: number
description: "The score of the specified player."
example: 1234.56
rank:
type: integer
description: "The zero-indexed rank of the specified player. (You may probably want to add `1` before displaying it to an user.)"
example: 0
201:
description: "Score submitted and updated"
content:
application/json:
schema:
type: object
properties:
score:
type: number
description: "The score of the specified player."
example: 2468.13
rank:
type: integer
description: "The zero-indexed rank of the specified player. (You may probably want to add `1` before displaying it to an user.)"
example: 0
401:
description: "Missing, invalid or malformed Authorization header"
content:
application/json:
schema:
type: string
example: "Missing Authorization header"
403:
description: "Invalid board token"
content:
application/json:
schema:
type: string
example: "Invalid board token"
502:
$ref: "#/components/responses/RedisCmdFailed"
504:
$ref: "#/components/responses/RedisConnFailed"
components:
securitySchemes:
XCreateToken:
type: http
scheme: "bearer"
bearerFormat: "setInEnvVars"
XBoardToken:
type: http
scheme: "bearer"
bearerFormat: "gVsuzIxgVfRx4RNl"
parameters:
board:
name: "board"
description: "The name of the board to operate on."
in: query
schema:
type: string
player:
name: "player"
description: "The name of the player to operate on."
in: query
schema:
type: string
offset:
name: "offset"
description: "The offset to start returning results from."
in: query
schema:
type: integer
size:
name: "size"
description: "How many results to return."
in: query
schema:
type: integer
minimum: 0
maximum: 500
responses:
RedisCmdFailed:
description: "Could not execute Redis command"
content:
application/json:
schema:
type: string
example: "Could not execute Redis command"
RedisConnFailed:
description: "Could not connect to Redis"
content:
application/json:
schema:
type: string
example: "Could not connect to Redis"