first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:48:15 +03:00
commit e6f3268c28
50 changed files with 4930 additions and 0 deletions

107
router/routers.go Normal file
View File

@@ -0,0 +1,107 @@
package router
import (
"encoding/json"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/gofiber/fiber/v3"
"goimgApi/accounts"
"goimgApi/images"
)
func SetupRoutes(app *fiber.App) {
app.Get("/", func(c fiber.Ctx) error {
return c.SendString("Go Image API Running")
})
app.Get("/uploads/*", func(c fiber.Ctx) error {
relPath := strings.TrimPrefix(c.Params("*"), "/")
if relPath == "" {
return fiber.ErrNotFound
}
cleanPath := filepath.Clean(relPath)
if cleanPath == "." || strings.HasPrefix(cleanPath, "..") {
return fiber.ErrForbidden
}
return c.SendFile(filepath.Join("uploads", cleanPath))
})
// Swagger setup
app.Get("/docs/swagger.json", func(c fiber.Ctx) error {
raw, err := loadSwaggerSpec()
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Swagger spec could not be loaded")
}
var spec map[string]any
if err := json.Unmarshal(raw, &spec); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Swagger spec is invalid")
}
delete(spec, "host")
delete(spec, "schemes")
return c.JSON(spec)
})
app.Get("/swagger", func(c fiber.Ctx) error {
c.Set("Content-Type", "text/html")
return c.SendString(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Swagger UI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.3.0/swagger-ui.css" />
</head>
<body style="margin:0;">
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.3.0/swagger-ui-bundle.js"></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: '/docs/swagger.json',
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>`)
})
authGroup := app.Group("/auth")
authGroup.Post("/register", accounts.Register)
authGroup.Post("/login", accounts.Login)
authGroup.Post("/refresh", accounts.Refresh)
adminGroup := app.Group("/admin", accounts.JWTMiddleware, accounts.AdminMiddleware)
adminGroup.Post("/users/:id/api-token", accounts.CreateApiToken)
adminGroup.Get("/images", images.AdminListImages)
imagesGroup := app.Group("/images", accounts.JWTMiddleware)
imagesGroup.Post("/", images.Upload)
imagesGroup.Get("/", images.ListImages)
imagesGroup.Get("/:id", images.GetImage)
// Process endpoint uses API token authentication (not JWT); keep it outside the JWT group
app.Get("/images/:id/process", images.Process)
}
func loadSwaggerSpec() ([]byte, error) {
if raw, err := os.ReadFile("./docs/swagger.json"); err == nil {
return raw, nil
}
_, currentFile, _, ok := runtime.Caller(0)
if !ok {
return nil, os.ErrNotExist
}
projectRoot := filepath.Dir(filepath.Dir(currentFile))
return os.ReadFile(filepath.Join(projectRoot, "docs", "swagger.json"))
}

74
router/routers_test.go Normal file
View File

@@ -0,0 +1,74 @@
package router
import (
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"github.com/gofiber/fiber/v3"
)
func TestSwaggerJSONUsesRequestOrigin(t *testing.T) {
app := fiber.New()
SetupRoutes(app)
req := httptest.NewRequest(http.MethodGet, "/docs/swagger.json", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf("request failed: %v", err)
}
t.Cleanup(func() {
_ = resp.Body.Close()
})
if resp.StatusCode != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, resp.StatusCode)
}
var spec map[string]any
if err := json.NewDecoder(resp.Body).Decode(&spec); err != nil {
t.Fatalf("failed to decode swagger json: %v", err)
}
if _, ok := spec["host"]; ok {
t.Fatal("swagger spec should not expose a fixed host")
}
if _, ok := spec["schemes"]; ok {
t.Fatal("swagger spec should not expose fixed schemes")
}
}
func TestUploadsAreServedStatically(t *testing.T) {
app := fiber.New()
SetupRoutes(app)
if err := os.MkdirAll("uploads", 0755); err != nil {
t.Fatalf("failed to create uploads dir: %v", err)
}
filename := "router-static-test.txt"
filePath := filepath.Join("uploads", filename)
if err := os.WriteFile(filePath, []byte("hello-image"), 0644); err != nil {
t.Fatalf("failed to write test file: %v", err)
}
t.Cleanup(func() {
_ = os.Remove(filePath)
})
req := httptest.NewRequest(http.MethodGet, "/uploads/"+filename, nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf("request failed: %v", err)
}
t.Cleanup(func() {
_ = resp.Body.Close()
})
if resp.StatusCode != http.StatusOK {
t.Fatalf("expected status %d, got %d", http.StatusOK, resp.StatusCode)
}
}