Merge pull request #1256 from acelaya-forks/feature/api-examples

Feature/api examples
This commit is contained in:
Alejandro Celaya 2021-12-09 19:09:02 +01:00 committed by GitHub
commit 2e3798b282
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 632 additions and 467 deletions

View File

@ -8,29 +8,12 @@ on:
- develop - develop
jobs: jobs:
lint:
runs-on: ubuntu-20.04
strategy:
matrix:
php-version: ['8.0']
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Use PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: composer
extensions: openswoole-4.8.1
coverage: none
- run: composer install --no-interaction --prefer-dist
- run: composer cs
static-analysis: static-analysis:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
php-version: ['8.0'] php-version: ['8.0']
command: ['cs', 'stan', 'swagger:validate']
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -42,7 +25,7 @@ jobs:
extensions: openswoole-4.8.1 extensions: openswoole-4.8.1
coverage: none coverage: none
- run: composer install --no-interaction --prefer-dist - run: composer install --no-interaction --prefer-dist
- run: composer stan - run: composer ${{ matrix.command }}
unit-tests: unit-tests:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ docs/swagger-ui*
docs/mercure.html docs/mercure.html
docker-compose.override.yml docker-compose.override.yml
.phpunit.result.cache .phpunit.result.cache
docs/swagger/swagger-inlined.json

View File

@ -37,6 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
### Fixed ### Fixed
* [#1206](https://github.com/shlinkio/shlink/issues/1206) Fixed debugging of the docker image, so that it does not run the commands with `-q` when the `SHELL_VERBOSITY` env var has been provided. * [#1206](https://github.com/shlinkio/shlink/issues/1206) Fixed debugging of the docker image, so that it does not run the commands with `-q` when the `SHELL_VERBOSITY` env var has been provided.
* [#1254](https://github.com/shlinkio/shlink/issues/1254) Fixed examples in swagger docs.
## [2.9.3] - 2021-11-15 ## [2.9.3] - 2021-11-15

View File

@ -61,6 +61,7 @@
"symfony/string": "^5.4" "symfony/string": "^5.4"
}, },
"require-dev": { "require-dev": {
"cebe/php-openapi": "^1.5",
"devster/ubench": "^2.1", "devster/ubench": "^2.1",
"dms/phpunit-arraysubset-asserts": "^0.3.0", "dms/phpunit-arraysubset-asserts": "^0.3.0",
"eaglewu/swoole-ide-helper": "dev-master", "eaglewu/swoole-ide-helper": "dev-master",
@ -145,6 +146,8 @@
"@parallel test:unit:ci test:db:sqlite:ci", "@parallel test:unit:ci test:db:sqlite:ci",
"@infect:ci" "@infect:ci"
], ],
"swagger:validate": "php-openapi validate docs/swagger/swagger.json",
"swagger:inline": "php-openapi inline docs/swagger/swagger.json docs/swagger/swagger-inlined.json",
"clean:dev": "rm -f data/database.sqlite && rm -f config/params/generated_config.php" "clean:dev": "rm -f data/database.sqlite && rm -f config/params/generated_config.php"
}, },
"scripts-descriptions": { "scripts-descriptions": {
@ -170,6 +173,8 @@
"infect:ci:unit": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing with existing reports and logs</>", "infect:ci:unit": "<fg=blue;options=bold>Checks unit tests quality applying mutation testing with existing reports and logs</>",
"infect:ci:db": "<fg=blue;options=bold>Checks db tests quality applying mutation testing with existing reports and logs</>", "infect:ci:db": "<fg=blue;options=bold>Checks db tests quality applying mutation testing with existing reports and logs</>",
"infect:test": "<fg=blue;options=bold>Runs unit and db tests, then checks tests quality applying mutation testing</>", "infect:test": "<fg=blue;options=bold>Runs unit and db tests, then checks tests quality applying mutation testing</>",
"swagger:validate": "<fg=blue;options=bold>Validates the swagger docs, making sure they fulfil the spec</>",
"swagger:inline": "<fg=blue;options=bold>Inlines swagger docs in a single file</>",
"clean:dev": "<fg=blue;options=bold>Deletes artifacts which are gitignored and could affect dev env</>" "clean:dev": "<fg=blue;options=bold>Deletes artifacts which are gitignored and could affect dev env</>"
}, },
"config": { "config": {

View File

@ -0,0 +1,9 @@
{
"value": {
"title": "Invalid data",
"type": "INVALID_ARGUMENT",
"detail": "Provided data is not valid",
"status": 400,
"invalidElements": ["maxVisits", "validSince"]
}
}

View File

@ -0,0 +1,9 @@
{
"value": {
"detail":"No URL found with short code \"abc123\"",
"title":"Short URL not found",
"type": "INVALID_SHORTCODE",
"status": 404,
"shortCode": "abc123"
}
}

View File

@ -0,0 +1,9 @@
{
"value": {
"detail": "Tag with name \"foo\" could not be found",
"title": "Tag not found",
"type": "TAG_NOT_FOUND",
"status": 404,
"tag": "foo"
}
}

View File

@ -13,16 +13,14 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/Health.json" "$ref": "../definitions/Health.json"
} },
} "example": {
}, "status": "pass",
"examples": { "version": "2.10.0",
"application/json": { "links": {
"status": "pass", "about": "https://shlink.io",
"version": "1.16.0", "project": "https://github.com/shlinkio/shlink"
"links": { }
"about": "https://shlink.io",
"project": "https://github.com/shlinkio/shlink"
} }
} }
} }
@ -33,21 +31,19 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/Health.json" "$ref": "../definitions/Health.json"
} },
} "example": {
}, "status": "fail",
"examples": { "version": "2.10.0",
"application/json": { "links": {
"status": "fail", "about": "https://shlink.io",
"version": "1.16.0", "project": "https://github.com/shlinkio/shlink"
"links": { }
"about": "https://shlink.io",
"project": "https://github.com/shlinkio/shlink"
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/json": { "application/json": {

View File

@ -117,79 +117,77 @@
} }
} }
} }
} },
} "example": {
}, "shortUrls": {
"examples": { "data": [
"application/json": { {
"shortUrls": { "shortCode": "12C18",
"data": [ "shortUrl": "https://doma.in/12C18",
{ "longUrl": "https://store.steampowered.com",
"shortCode": "12C18", "dateCreated": "2016-08-21T20:34:16+02:00",
"shortUrl": "https://doma.in/12C18", "visitsCount": 328,
"longUrl": "https://store.steampowered.com", "tags": [
"dateCreated": "2016-08-21T20:34:16+02:00", "games",
"visitsCount": 328, "tech"
"tags": [ ],
"games", "meta": {
"tech" "validSince": "2017-01-21T00:00:00+02:00",
], "validUntil": null,
"meta": { "maxVisits": 100
"validSince": "2017-01-21T00:00:00+02:00", },
"validUntil": null, "domain": null,
"maxVisits": 100 "title": "Welcome to Steam",
"crawlable": false
}, },
"domain": null, {
"title": "Welcome to Steam", "shortCode": "12Kb3",
"crawlable": false "shortUrl": "https://doma.in/12Kb3",
}, "longUrl": "https://shlink.io",
{ "dateCreated": "2016-05-01T20:34:16+02:00",
"shortCode": "12Kb3", "visitsCount": 1029,
"shortUrl": "https://doma.in/12Kb3", "tags": [
"longUrl": "https://shlink.io", "shlink"
"dateCreated": "2016-05-01T20:34:16+02:00", ],
"visitsCount": 1029, "meta": {
"tags": [ "validSince": null,
"shlink" "validUntil": null,
], "maxVisits": null
"meta": { },
"validSince": null, "domain": null,
"validUntil": null, "title": null,
"maxVisits": null "crawlable": false
}, },
"domain": null, {
"title": null, "shortCode": "123bA",
"crawlable": false "shortUrl": "https://example.com/123bA",
}, "longUrl": "https://www.google.com",
{ "dateCreated": "2015-10-01T20:34:16+02:00",
"shortCode": "123bA", "visitsCount": 25,
"shortUrl": "https://example.com/123bA", "tags": [],
"longUrl": "https://www.google.com", "meta": {
"dateCreated": "2015-10-01T20:34:16+02:00", "validSince": "2017-01-21T00:00:00+02:00",
"visitsCount": 25, "validUntil": null,
"tags": [], "maxVisits": null
"meta": { },
"validSince": "2017-01-21T00:00:00+02:00", "domain": "example.com",
"validUntil": null, "title": null,
"maxVisits": null "crawlable": false
}, }
"domain": "example.com", ],
"title": null, "pagination": {
"crawlable": false "currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -267,28 +265,26 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/ShortUrl.json" "$ref": "../definitions/ShortUrl.json"
}
}
},
"examples": {
"application/json": {
"shortCode": "12C18",
"shortUrl": "https://doma.in/12C18",
"longUrl": "https://store.steampowered.com",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 500
}, },
"domain": null, "example": {
"title": null, "shortCode": "12C18",
"crawlable": false "shortUrl": "https://doma.in/12C18",
"longUrl": "https://store.steampowered.com",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 500
},
"domain": null,
"title": null,
"crawlable": false
}
} }
} }
}, },
@ -326,15 +322,42 @@
"customSlug": { "customSlug": {
"type": "string", "type": "string",
"description": "Provided custom slug when the error type is INVALID_SLUG" "description": "Provided custom slug when the error type is INVALID_SLUG"
},
"domain": {
"type": "string",
"description": "The domain for which you were trying to create the new short URL"
} }
} }
} }
] ]
},
"examples": {
"Invalid arguments": {
"$ref": "../examples/short-url-invalid-args.json"
},
"Invalid long URL": {
"value": {
"title": "Invalid URL",
"type": "INVALID_URL",
"detail": "Provided URL foo is invalid. Try with a different one.",
"status": 400,
"url": "https://invalid-url.com"
}
},
"Non-unique slug": {
"value": {
"title": "Invalid custom slug",
"type": "INVALID_SLUG",
"detail": "Provided slug \"my-slug\" is already in use.",
"status": 400,
"customSlug": "my-slug"
}
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -49,35 +49,33 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/ShortUrl.json" "$ref": "../definitions/ShortUrl.json"
},
"example": {
"longUrl": "https://github.com/shlinkio/shlink",
"shortUrl": "https://doma.in/abc123",
"shortCode": "abc123",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
},
"domain": null,
"title": null,
"crawlable": false
} }
}, },
"text/plain": { "text/plain": {
"schema": { "schema": {
"type": "string" "type": "string"
}
}
},
"examples": {
"application/json": {
"longUrl": "https://github.com/shlinkio/shlink",
"shortUrl": "https://doma.in/abc123",
"shortCode": "abc123",
"dateCreated": "2016-08-21T20:34:16+02:00",
"visitsCount": 0,
"tags": [
"games",
"tech"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
}, },
"domain": null, "example": "https://doma.in/abc123"
"title": null, }
"crawlable": false
},
"text/plain": "https://doma.in/abc123"
} }
}, },
"400": { "400": {
@ -86,26 +84,24 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"title": "Invalid URL",
"type": "INVALID_URL",
"detail": "Provided URL foo is invalid. Try with a different one.",
"status": 400,
"url": "https://invalid-url.com"
} }
}, },
"text/plain": { "text/plain": {
"schema": { "schema": {
"type": "string" "type": "string"
} },
"example": "INVALID_URL"
} }
},
"examples": {
"application/problem+json": {
"title": "Invalid URL",
"type": "INVALID_URL",
"detail": "Provided URL foo is invalid. Try with a different one.",
"status": 400,
"url": "https://invalid-url.com"
},
"text/plain": "INVALID_URL"
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -118,13 +114,6 @@
"type": "string" "type": "string"
} }
} }
},
"examples": {
"application/problem+json": {
"error": "INTERNAL_SERVER_ERROR",
"message": "Unexpected error occurred"
},
"text/plain": "INTERNAL_SERVER_ERROR"
} }
} }
} }

View File

@ -35,27 +35,25 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/ShortUrl.json" "$ref": "../definitions/ShortUrl.json"
}
}
},
"examples": {
"application/json": {
"shortCode": "12Kb3",
"shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
}, },
"domain": null, "example": {
"title": null, "shortCode": "12Kb3",
"crawlable": false "shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
},
"domain": null,
"title": null,
"crawlable": false
}
} }
} }
}, },
@ -64,12 +62,35 @@
"content": { "content": {
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "allOf": [
{
"$ref": "../definitions/Error.json"
},
{
"type": "object",
"required": ["shortCode"],
"properties": {
"shortCode": {
"type": "string",
"description": "The short code with which we tried to find the short URL"
},
"domain": {
"type": "string",
"description": "The domain with which we tried to find the short URL"
}
}
}
]
},
"examples": {
"Not found": {
"$ref": "../examples/short-url-not-found.json"
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -129,27 +150,25 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/ShortUrl.json" "$ref": "../definitions/ShortUrl.json"
}
}
},
"examples": {
"application/json": {
"shortCode": "12Kb3",
"shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
}, },
"domain": null, "example": {
"title": "Shlink - The URL shortener", "shortCode": "12Kb3",
"crawlable": false "shortUrl": "https://doma.in/12Kb3",
"longUrl": "https://shlink.io",
"dateCreated": "2016-05-01T20:34:16+02:00",
"visitsCount": 1029,
"tags": [
"shlink"
],
"meta": {
"validSince": "2017-01-21T00:00:00+02:00",
"validUntil": null,
"maxVisits": 100
},
"domain": null,
"title": "Shlink - The URL shortener",
"crawlable": false
}
} }
} }
}, },
@ -182,21 +201,49 @@
} }
} }
] ]
},
"examples": {
"Invalid arguments": {
"$ref": "../examples/short-url-invalid-args.json"
}
} }
} }
} }
}, },
"404": { "404": {
"description": "No short URL was found for provided short code.", "description": "No URL was found for provided short code.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "allOf": [
{
"$ref": "../definitions/Error.json"
},
{
"type": "object",
"required": ["shortCode"],
"properties": {
"shortCode": {
"type": "string",
"description": "The short code with which we tried to find the short URL"
},
"domain": {
"type": "string",
"description": "The domain with which we tried to find the short URL"
}
}
}
]
},
"examples": {
"Not found": {
"$ref": "../examples/short-url-not-found.json"
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -247,30 +294,75 @@
"content": { "content": {
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "allOf": [
{
"$ref": "../definitions/Error.json"
},
{
"type": "object",
"required": ["shortCode", "threshold"],
"properties": {
"shortCode": {
"type": "string",
"description": "The short code with which we tried to find the short URL to delete"
},
"domain": {
"type": "string",
"description": "The domain with which we tried to find the short URL to delete"
},
"threshold": {
"type": "number",
"description": "The amount of visits currently configured as threshold to allow deleting short UYRLs or not"
}
}
}
]
},
"example": {
"title": "Cannot delete short URL",
"type": "INVALID_SHORTCODE_DELETION",
"detail": "Impossible to delete short URL with short code \"abc123\", since it has more than \"15\" visits.",
"status": 422,
"shortCode": "abc123",
"threshold": 15
} }
} }
},
"examples": {
"application/problem+json": {
"title": "Cannot delete short URL",
"type": "INVALID_SHORTCODE_DELETION",
"detail": "It is not possible to delete URL with short code \"abc123\" because it has reached more than \"15\" visits.",
"status": 422
}
} }
}, },
"404": { "404": {
"description": "No short URL was found for provided short code.", "description": "No URL was found for provided short code.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "allOf": [
{
"$ref": "../definitions/Error.json"
},
{
"type": "object",
"required": ["shortCode"],
"properties": {
"shortCode": {
"type": "string",
"description": "The short code with which we tried to find the short URL"
},
"domain": {
"type": "string",
"description": "The domain with which we tried to find the short URL"
}
}
}
]
},
"examples": {
"Not found": {
"$ref": "../examples/short-url-not-found.json"
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -69,14 +69,6 @@
} }
} }
} }
},
"examples": {
"application/json": {
"tags": [
"games",
"tech"
]
}
} }
}, },
"400": { "400": {
@ -99,7 +91,7 @@
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/json": { "application/json": {

View File

@ -97,49 +97,47 @@
} }
} }
} }
} },
} "example": {
}, "visits": {
"examples": { "data": [
"application/json": { {
"visits": { "referer": "https://twitter.com",
"data": [ "date": "2015-08-20T05:05:03+04:00",
{ "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"referer": "https://twitter.com", "visitLocation": null,
"date": "2015-08-20T05:05:03+04:00", "potentialBot": false
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"visitLocation": null,
"potentialBot": false
},
{
"referer": "https://t.co",
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"visitLocation": {
"cityName": "Cupertino",
"countryCode": "US",
"countryName": "United States",
"latitude": 37.3042,
"longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
}, },
"potentialBot": false {
}, "referer": "https://t.co",
{ "date": "2015-08-20T05:05:03+04:00",
"referer": null, "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"date": "2015-08-20T05:05:03+04:00", "visitLocation": {
"userAgent": "some_web_crawler/1.4", "cityName": "Cupertino",
"visitLocation": null, "countryCode": "US",
"potentialBot": true "countryName": "United States",
"latitude": 37.3042,
"longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
},
"potentialBot": false
},
{
"referer": null,
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "some_web_crawler/1.4",
"visitLocation": null,
"potentialBot": true
}
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
} }
} }
@ -151,11 +149,16 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"examples": {
"Short URL not found": {
"$ref": "../examples/short-url-not-found.json"
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -57,23 +57,47 @@
} }
} }
} }
} },
} "examples": {
}, "Without stats": {
"examples": { "value": {
"application/json": { "tags": {
"tags": { "data": [
"data": [ "games",
"games", "php",
"php", "shlink",
"shlink", "tech"
"tech" ]
] }
}
},
"With stats": {
"value": {
"tags": {
"data": [
"games",
"shlink"
],
"stats": [
{
"tag": "games",
"shortUrlsCount": 10,
"visitsCount": 521
},
{
"tag": "shlink",
"shortUrlsCount": 7,
"visitsCount": 1087
}
]
}
}
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -149,21 +173,9 @@
} }
} }
} }
},
"examples": {
"application/json": {
"tags": {
"data": [
"games",
"php",
"shlink",
"tech"
]
}
}
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -228,6 +240,13 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"title": "Invalid data",
"type": "INVALID_ARGUMENT",
"detail": "Provided data is not valid",
"status": 400,
"invalidElements": ["oldName", "newName"]
} }
} }
} }
@ -238,6 +257,12 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"detail": "You are not allowed to rename tags",
"title": "Forbidden tag operation",
"type": "FORBIDDEN_OPERATION",
"status": 403
} }
} }
} }
@ -248,6 +273,11 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"examples": {
"Tag not found": {
"$ref": "../examples/tag-not-found.json"
}
} }
} }
} }
@ -258,11 +288,19 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"detail": "You cannot rename tag foo, because it already exists",
"title": "Tag conflict",
"type": "TAG_CONFLICT",
"status": 409,
"oldName": "bar",
"newName": "foo"
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {
@ -314,11 +352,17 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"detail": "You are not allowed to delete tags",
"title": "Forbidden tag operation",
"type": "FORBIDDEN_OPERATION",
"status": 403
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -53,51 +53,49 @@
} }
} }
} }
} },
} "example": {
}, "domains": {
"examples": { "data": [
"application/json": { {
"domains": { "domain": "example.com",
"data": [ "isDefault": true,
{ "redirects": {
"domain": "example.com", "baseUrlRedirect": "https://example.com/my-landing-page",
"isDefault": true, "regular404Redirect": null,
"redirects": { "invalidShortUrlRedirect": "https://example.com/invalid-url"
"baseUrlRedirect": "https://example.com/my-landing-page", }
"regular404Redirect": null, },
"invalidShortUrlRedirect": "https://example.com/invalid-url" {
} "domain": "aaa.com",
}, "isDefault": false,
{ "redirects": {
"domain": "aaa.com", "baseUrlRedirect": null,
"isDefault": false, "regular404Redirect": null,
"redirects": { "invalidShortUrlRedirect": null
"baseUrlRedirect": null, }
"regular404Redirect": null, },
"invalidShortUrlRedirect": null {
} "domain": "bbb.com",
}, "isDefault": false,
{ "redirects": {
"domain": "bbb.com", "baseUrlRedirect": null,
"isDefault": false, "regular404Redirect": null,
"redirects": { "invalidShortUrlRedirect": "https://example.com/invalid-url"
"baseUrlRedirect": null, }
"regular404Redirect": null,
"invalidShortUrlRedirect": "https://example.com/invalid-url"
} }
],
"defaultRedirects": {
"baseUrlRedirect": "https://somewhere.com",
"regular404Redirect": null,
"invalidShortUrlRedirect": null
} }
],
"defaultRedirects": {
"baseUrlRedirect": "https://somewhere.com",
"regular404Redirect": null,
"invalidShortUrlRedirect": null
} }
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -55,15 +55,13 @@
"$ref": "../definitions/NotFoundRedirects.json" "$ref": "../definitions/NotFoundRedirects.json"
} }
] ]
},
"example": {
"baseUrlRedirect": "https://example.com/my-landing-page",
"regular404Redirect": null,
"invalidShortUrlRedirect": "https://example.com/invalid-url"
} }
} }
},
"examples": {
"application/json": {
"baseUrlRedirect": "https://example.com/my-landing-page",
"regular404Redirect": null,
"invalidShortUrlRedirect": "https://example.com/invalid-url"
}
} }
}, },
"400": { "400": {
@ -95,11 +93,18 @@
} }
} }
] ]
},
"example": {
"title": "Invalid data",
"type": "INVALID_ARGUMENT",
"detail": "Provided data is not valid",
"status": 400,
"invalidElements": ["domain", "invalidShortUrlRedirect"]
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -23,15 +23,13 @@
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "../definitions/MercureInfo.json" "$ref": "../definitions/MercureInfo.json"
},
"example": {
"mercureHubUrl": "https://example.com/.well-known/mercure",
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTaGxpbmsiLCJpYXQiOjE1ODY2ODY3MzIsImV4cCI6MTU4Njk0NTkzMiwibWVyY3VyZSI6eyJzdWJzY3JpYmUiOltdfX0.P-519lgU7dFz0bbNlRG1CXyqugGbaHon4kw6fu4QBdQ",
"jwtExpiration": "2020-04-15T12:18:52+02:00"
} }
} }
},
"examples": {
"application/json": {
"mercureHubUrl": "https://example.com/.well-known/mercure",
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTaGxpbmsiLCJpYXQiOjE1ODY2ODY3MzIsImV4cCI6MTU4Njk0NTkzMiwibWVyY3VyZSI6eyJzdWJzY3JpYmUiOltdfX0.P-519lgU7dFz0bbNlRG1CXyqugGbaHon4kw6fu4QBdQ",
"jwtExpiration": "2020-04-15T12:18:52+02:00"
}
} }
}, },
"501": { "501": {
@ -40,19 +38,17 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"example": {
"title": "Mercure integration not configured",
"type": "MERCURE_NOT_CONFIGURED",
"detail": "This Shlink instance is not integrated with a mercure hub.",
"status": 501
} }
} }
},
"examples": {
"application/json": {
"title": "Mercure integration not configured",
"type": "MERCURE_NOT_CONFIGURED",
"detail": "This Shlink instance is not integrated with a mercure hub.",
"status": 501
}
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -94,49 +94,47 @@
} }
} }
} }
} },
} "example": {
}, "visits": {
"examples": { "data": [
"application/json": { {
"visits": { "referer": "https://twitter.com",
"data": [ "date": "2015-08-20T05:05:03+04:00",
{ "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"referer": "https://twitter.com", "visitLocation": null,
"date": "2015-08-20T05:05:03+04:00", "potentialBot": false
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"visitLocation": null,
"potentialBot": false
},
{
"referer": "https://t.co",
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"visitLocation": {
"cityName": "Cupertino",
"countryCode": "US",
"countryName": "United States",
"latitude": 37.3042,
"longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
}, },
"potentialBot": false {
}, "referer": "https://t.co",
{ "date": "2015-08-20T05:05:03+04:00",
"referer": null, "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"date": "2015-08-20T05:05:03+04:00", "visitLocation": {
"userAgent": "some_web_crawler/1.4", "cityName": "Cupertino",
"visitLocation": null, "countryCode": "US",
"potentialBot": true "countryName": "United States",
"latitude": 37.3042,
"longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
},
"potentialBot": false
},
{
"referer": null,
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "some_web_crawler/1.4",
"visitLocation": null,
"potentialBot": true
}
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
} }
} }
@ -148,11 +146,16 @@
"application/problem+json": { "application/problem+json": {
"schema": { "schema": {
"$ref": "../definitions/Error.json" "$ref": "../definitions/Error.json"
},
"examples": {
"Tag not found": {
"$ref": "../examples/tag-not-found.json"
}
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -28,19 +28,17 @@
"$ref": "../definitions/VisitStats.json" "$ref": "../definitions/VisitStats.json"
} }
} }
} },
} "example": {
}, "visits": {
"examples": { "visitsCount": 1569874,
"application/json": { "orphanVisitsCount": 71345
"visits": { }
"visitsCount": 1569874,
"orphanVisitsCount": 71345
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -85,61 +85,59 @@
} }
} }
} }
} },
} "example": {
}, "visits": {
"examples": { "data": [
"application/json": { {
"visits": { "referer": "https://twitter.com",
"data": [ "date": "2015-08-20T05:05:03+04:00",
{ "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
"referer": "https://twitter.com", "visitLocation": null,
"date": "2015-08-20T05:05:03+04:00", "potentialBot": false,
"userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0 Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0", "visitedUrl": "https://doma.in",
"visitLocation": null, "type": "base_url"
"potentialBot": false,
"visitedUrl": "https://doma.in",
"type": "base_url"
},
{
"referer": "https://t.co",
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"visitLocation": {
"cityName": "Cupertino",
"countryCode": "US",
"countryName": "United States",
"latitude": 37.3042,
"longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
}, },
"potentialBot": false, {
"visitedUrl": "https://doma.in/foo", "referer": "https://t.co",
"type": "invalid_short_url" "date": "2015-08-20T05:05:03+04:00",
}, "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
{ "visitLocation": {
"referer": null, "cityName": "Cupertino",
"date": "2015-08-20T05:05:03+04:00", "countryCode": "US",
"userAgent": "some_web_crawler/1.4", "countryName": "United States",
"visitLocation": null, "latitude": 37.3042,
"potentialBot": true, "longitude": -122.0946,
"visitedUrl": "https://doma.in/foo/bar/baz", "regionName": "California",
"type": "regular_404" "timezone": "America/Los_Angeles"
},
"potentialBot": false,
"visitedUrl": "https://doma.in/foo",
"type": "invalid_short_url"
},
{
"referer": null,
"date": "2015-08-20T05:05:03+04:00",
"userAgent": "some_web_crawler/1.4",
"visitLocation": null,
"potentialBot": true,
"visitedUrl": "https://doma.in/foo/bar/baz",
"type": "regular_404"
}
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
],
"pagination": {
"currentPage": 5,
"pagesCount": 12,
"itemsPerPage": 10,
"itemsInCurrentPage": 10,
"totalItems": 115
} }
} }
} }
} }
}, },
"500": { "default": {
"description": "Unexpected error.", "description": "Unexpected error.",
"content": { "content": {
"application/problem+json": { "application/problem+json": {

View File

@ -60,6 +60,17 @@
"enum": ["L", "M", "Q", "H"], "enum": ["L", "M", "Q", "H"],
"default": "L" "default": "L"
} }
},
{
"name": "roundBlockSize",
"in": "query",
"description": "Allows to disable block size rounding, which might reduce the readability of the QR code, but ensures no extra margin is added.",
"required": false,
"schema": {
"type": "string",
"enum": ["true", "false"],
"default": "false"
}
} }
], ],
"responses": { "responses": {

View File

@ -21,7 +21,7 @@
"name": "size", "name": "size",
"in": "path", "in": "path",
"description": "The size of the image to be returned.", "description": "The size of the image to be returned.",
"required": false, "required": true,
"schema": { "schema": {
"type": "integer", "type": "integer",
"minimum": 50, "minimum": 50,