Skip to content

Commit

Permalink
feat: add endpoint for getting data about a given document (#81)
Browse files Browse the repository at this point in the history
* First pass at #75

* doc: add openapi spec for doc metadata endpoint

* test: add tests for HandleDocMetadata
  • Loading branch information
kaiiorg committed Jan 2, 2024
1 parent 66c7970 commit c031982
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 1 deletion.
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ require (
github.com/gin-gonic/contrib v0.0.0-20221130124618-7e01895a63f2
github.com/gin-gonic/gin v1.9.1
github.com/glebarez/sqlite v1.10.0
github.com/google/uuid v1.5.0
github.com/joho/godotenv v1.5.1
github.com/stretchr/testify v1.8.4
gorm.io/gorm v1.25.5
)

require (
github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand All @@ -24,7 +27,6 @@ require (
github.com/go-playground/validator/v10 v10.16.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand All @@ -35,6 +37,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
Expand Down
45 changes: 45 additions & 0 deletions handlers/docs/handleDocMetadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package handlers

import (
"errors"
"log"
"net/http"
"os"
"path/filepath"

"github.com/kevinanielsen/go-fast-cdn/util"

"github.com/gin-gonic/gin"
)

func HandleDocMetadata(c *gin.Context) {
fileName := c.Param("filename")
if fileName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Doc name is required",
})
return
}

filePath := filepath.Join(util.ExPath, "uploads", "docs", fileName)
stat, err := os.Stat(filePath)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
c.JSON(http.StatusNotFound, gin.H{
"error": "Doc does not exist",
})
} else {
log.Printf("Failed to get document %s: %s\n", fileName, err.Error())
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Internal error",
})
}
return
}

c.JSON(http.StatusOK, gin.H{
"filename": fileName,
"download_url": c.Request.Host + "/api/cdn/download/docs/" + fileName,
"file_size": stat.Size(),
})
}
92 changes: 92 additions & 0 deletions handlers/docs/handleDocMetadata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package handlers

import (
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"

"github.com/kevinanielsen/go-fast-cdn/util"

"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
)

func TestHandleDocMetadata_NoError(t *testing.T) {
// Arrange
testFileName := uuid.NewString()
testFileDir := filepath.Join(util.ExPath, "uploads", "docs")
defer os.RemoveAll(filepath.Join(util.ExPath, "uploads"))
err := os.MkdirAll(testFileDir, 0766)
require.NoError(t, err)
testFilePath := filepath.Join(testFileDir, testFileName)
testFileContents := uuid.NewString()
err = os.WriteFile(testFilePath, []byte(testFileContents), 0666)
require.NoError(t, err)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/test", nil)
c.Params = []gin.Param{{
Key: "filename",
Value: testFileName,
}}

// Act
HandleDocMetadata(c)

// Assert
require.Equal(t, http.StatusOK, w.Result().StatusCode)
result := map[string]interface{}{}
err = json.NewDecoder(w.Body).Decode(&result)
require.NoError(t, err)
require.Contains(t, result, "filename")
require.Equal(t, result["filename"], testFileName)
require.Contains(t, result, "download_url")
require.NotEmpty(t, result["download_url"])
require.Contains(t, result, "file_size")
require.Equal(t, float64(len(testFileContents)), result["file_size"])
}

func TestHandleDocMetadata_NotFound(t *testing.T) {
// Arrange
testFileName := uuid.NewString()
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/test", nil)
c.Params = []gin.Param{{
Key: "filename",
Value: testFileName,
}}

// Act
HandleDocMetadata(c)

// Assert
require.Equal(t, http.StatusNotFound, w.Result().StatusCode)
result := map[string]interface{}{}
err := json.NewDecoder(w.Body).Decode(&result)
require.NoError(t, err)
require.Contains(t, result, "error")
require.Equal(t, result["error"], "Doc does not exist")
}

func TestHandleDocMetadata_NameNotProvided(t *testing.T) {
// Arrange
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodGet, "/test", nil)

// Act
HandleDocMetadata(c)

// Assert
require.Equal(t, http.StatusBadRequest, w.Result().StatusCode)
result := map[string]interface{}{}
err := json.NewDecoder(w.Body).Decode(&result)
require.NoError(t, err)
require.Contains(t, result, "error")
require.Equal(t, result["error"], "Doc name is required")
}
1 change: 1 addition & 0 deletions router/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func AddApiRoutes(r *gin.Engine) {
{
cdn.GET("/size", handlers.GetSizeHandler)
cdn.GET("/doc/all", dHandlers.HandleAllDocs)
cdn.GET("/doc/:filename", dHandlers.HandleDocMetadata)
cdn.GET("/image/all", iHandlers.HandleAllImages)
cdn.POST("/drop/database", dbHandlers.HandleDropDB)
cdn.Static("/download/images", util.ExPath+"/uploads/images")
Expand Down
61 changes: 61 additions & 0 deletions static/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,67 @@
}
}
},
"/api/cdn/doc/{fileName}": {
"get": {
"description": "Retrieves metadata about the document",
"responses": {
"400": {
"description": "Document filename was not provided",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": { "type": "string" }
}
}
}
}
},
"404": {
"description": "Document was not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": { "type": "string" }
}
}
}
}
},
"500": {
"description": "Unknown error while trying to retrieve the document",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": { "type": "string" }
}
}
}
}
},
"200": {
"description": "Metadata about the document",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"filename": { "type": "string" },
"download_url":{ "type": "string" },
"file_size": { "type": "number" }
}
}
}
}
}
}
}
},
"/api/cdn/image/all": {
"get": {
"summary": "Get all images",
Expand Down

0 comments on commit c031982

Please sign in to comment.