Skip to content

Commit

Permalink
feat: adds documentation (#20)
Browse files Browse the repository at this point in the history
- Creates Swagger docs (closes #19)
- Adds example for patch /short/:id
- Minor fixes on documentation
- Enables github pages with docs
  • Loading branch information
bolovsky authored Aug 23, 2023
1 parent 1680a29 commit afa2393
Show file tree
Hide file tree
Showing 9 changed files with 964 additions and 7 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@ migration/force:
.PHONY: image-push
image-push:
@build-tools/tag.sh

.PHONY: docs
docs:
@swag init --parseDependency --parseInternal --parseDepth 1
@rm docs/docs.go
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ you can use either `cockroach` or `postgres` as value for the `DB_ADAPTOR`

If you want to use `cockroach`, you can create a free account [here](https://cockroachlabs.cloud/)

Bellow are a few examples of how to use the API. You can find the documentation [here](https://doutorfinancas.github.io/pun-sho/)

### Create a short link
```bash
read -r -d '' BODY <<EOF
Expand Down Expand Up @@ -84,6 +86,43 @@ This would render an answer like:
}
```

### Edit a short link
It's also possible to edit a shortlink, by using the PATCH method

```bash
read -r -d '' BODY <<EOF
{
"link": "https://www.google.pt/",
"TTL": "2023-03-25T23:59:59Z",
"redirection_limit": 5,
"cancel": false,
}
EOF

curl -XPATCH http://localhost:8080/api/v1/short/4b677dfe-e17a-46e7-9cd2-25a45e8cb19c \
-H 'token: ThisIsA5uper$ecureAPIToken' \
-H 'Content-Type: application/json' \
-d $BODY
```

The response is equal to the POST one:
```json
{
"id":"4b677dfe-e17a-46e7-9cd2-25a45e8cb19c",
"link":"https://www.google.pt/",
"TTL":"2023-03-25T23:59:59Z",
"redirection_limit": 5,
"created_at":"2023-03-20T10:50:38.399449Z",
"deleted_at":null,
"accesses":null,
"qr_code": "data:image/png;base64,ASfojih134kjhas9f8798134lk2fasf...",
"short_link":"https://env.configured.domain/s/SEdeyZByeP",
"visits":0,
"redirects":0
}
```

### Preview QR code
If you want to preview the QR code only, you can use the preview endpoint with the same body as above
No TTL exists in that endpoint though (as its only preview mode), and the link is exactly the one you sent
```bash
Expand Down Expand Up @@ -214,5 +253,5 @@ we will be releasing 0.X until we bind a contract to the API
- [ ] Dashboard with overview
- [ ] Ability to track a specific link data
- [ ] Show list of links with filters (by date range, status)
- [ ] Allow better security (oauth2 or even simple jwt)
- [ ] Add GitHub pages with openapi/swagger definition
- [ ] Allow better security (variable API Key, oauth2 or even simple jwt)
- [X] Add GitHub pages with openapi/swagger definition #19
19 changes: 15 additions & 4 deletions api/preview.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,26 @@ func NewPreviewHandler(qrSvc *service.QRCodeService) HTTPHandler {
}

func (h *previewHandler) Routes(rg *gin.RouterGroup) {
rg.POST("", h.CreateLink)
rg.POST("/", h.CreateLink)
rg.POST("", h.CreatePreview)
rg.POST("/", h.CreatePreview)
}

func (h *previewHandler) Group() *string {
return str.ToStringNil("preview")
}

func (h *previewHandler) CreateLink(c *gin.Context) {
// CreatePreview godoc
// @Tags Preview
// @Summary Creates a QR Code preview for a given url
// @Schemes
// @Description Creates a QR Code preview for a given url
// @Param token header string false "Authorization token"
// @Param request body request.GeneratePreview true "Request"
// @Produce json
// @Success 201 {object} response.GeneratePreviewResponse "response"
// @Failure 400 {object} response.FailureResponse "error"
// @Router /preview [post]
func (h *previewHandler) CreatePreview(c *gin.Context) {
m := &request.GeneratePreview{}
err := c.BindJSON(m)

Expand All @@ -44,7 +55,7 @@ func (h *previewHandler) CreateLink(c *gin.Context) {
if err != nil {
c.JSON(
http.StatusBadRequest,
response.NewFailure("kaput, no save"),
response.NewFailure("failed to generate preview"),
)
return
}
Expand Down
60 changes: 59 additions & 1 deletion api/shortener.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ func (h *shortenerHandler) Group() *string {
return str.ToStringNil("short")
}

// GetLinkInformation godoc
// @Tags Short
// @Summary get your shortlink information
// @Schemes
// @Description retrieves full information for the give shortlink
// @Param token header string false "Authorization token"
// @Param id path string true "ShortLink ID"
// @Success 200 {object} entity.Shorty "response"
// @Failure 400 {object} response.FailureResponse "error"
// @Failure 404 {object} response.FailureResponse "not found"
// @Router /short/{id} [get]
func (h *shortenerHandler) GetLinkInformation(c *gin.Context) {
id := c.Param("id")
if id == "" {
Expand All @@ -52,6 +63,16 @@ func (h *shortenerHandler) GetLinkInformation(c *gin.Context) {
c.JSON(http.StatusOK, shorty)
}

// ListLinks godoc
// @Tags Short
// @Summary Lists your shorlinks
// @Schemes
// @Description Lists all the shortlinks available
// @Param token header string false "Authorization token"
// @Produce json
// @Success 200 {object} []entity.Shorty "response"
// @Failure 400 {object} response.FailureResponse "error"
// @Router /short [get]
func (h *shortenerHandler) ListLinks(c *gin.Context) {
limitStr := c.Query("limit")
offsetStr := c.Query("offset")
Expand All @@ -77,6 +98,17 @@ func (h *shortenerHandler) ListLinks(c *gin.Context) {
c.JSON(http.StatusOK, links)
}

// CreateLink godoc
// @Tags Short
// @Summary Creates a shortlink for a given url
// @Schemes
// @Description Creates a shortlink for a given url, optionally setting a ttl and a redirection limit
// @Param token header string false "Authorization token"
// @Param request body request.CreateShorty true "Request"
// @Produce json
// @Success 201 {object} entity.Shorty "response"
// @Failure 400 {object} response.FailureResponse "error"
// @Router /short [post]
func (h *shortenerHandler) CreateLink(c *gin.Context) {
m := &request.CreateShorty{}
err := c.BindJSON(m)
Expand All @@ -100,6 +132,19 @@ func (h *shortenerHandler) CreateLink(c *gin.Context) {
c.JSON(http.StatusCreated, s)
}

// EditLink godoc
// @Tags Short
// @Summary Edits a shortlink
// @Schemes
// @Description Edits a shortlink, allowing to set TTL, cancel the link or change the redirection limit or associated link
// @Param token header string false "Authorization token"
// @Param id path string true "ShortLink ID"
// @Param request body request.UpdateShorty true "Request"
// @Produce json
// @Success 200 {object} entity.Shorty "response"
// @Failure 400 {object} response.FailureResponse "error"
// @Failure 404 {object} response.FailureResponse "not found"
// @Router /short/{id} [patch]
func (h *shortenerHandler) EditLink(c *gin.Context) {
id := c.Param("id")
m := &request.UpdateShorty{}
Expand Down Expand Up @@ -130,6 +175,19 @@ func (h *shortenerHandler) EditLink(c *gin.Context) {
c.JSON(http.StatusOK, updatedShorty)
}

// RemoveLink godoc
// @Tags Short
// @Summary Deletes a shortlink
// @Schemes
// @Description Deletes a shortlink
// @Param token header string false "Authorization token"
// @Param id path string true "ShortLink ID"
// @Param request body request.UpdateShorty true "Request"
// @Produce json
// @Success 204 string false ""
// @Failure 400 {object} response.FailureResponse "error"
// @Failure 404 {object} response.FailureResponse "not found"
// @Router /short/{id} [delete]
func (h *shortenerHandler) RemoveLink(c *gin.Context) {
id := c.Param("id")
if id == "" {
Expand All @@ -146,5 +204,5 @@ func (h *shortenerHandler) RemoveLink(c *gin.Context) {
response.NewFailure("kaput, no delete"),
)
}
c.JSON(http.StatusOK, nil)
c.JSON(http.StatusNoContent, nil)
}
Binary file added docs/favicon.ico
Binary file not shown.
30 changes: 30 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<html>
<head>
<!-- Load the latest Swagger UI code and style from npm using unpkg.com -->
<script src="https://unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@3/swagger-ui.css"/>
<title>Pun-Sho API</title>
<link rel="shortcut icon" href="/pun-sho/favicon.ico">
</head>
<body>
<div id="swagger-ui"></div> <!-- Div to hold the UI component -->
<script>
window.onload = function () {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "swagger.json", //Location of Open API spec in the repo
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
})
window.ui = ui
}
</script>
</body>
</html>
Loading

0 comments on commit afa2393

Please sign in to comment.