Skip to content

Commit

Permalink
♻️ Add: openapi command
Browse files Browse the repository at this point in the history
  • Loading branch information
naohito-T committed Apr 30, 2024
1 parent 6e2c48d commit cbdd2e8
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 48 deletions.
5 changes: 4 additions & 1 deletion backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ lint-f:
build:
GOARCH=arm64 GOOS=linux go build -o bin/main cmd/api/main.go

build-openapi:
go run ./cmd/api/main.go openapi >./api/openapi.yaml

# --------------------------
# Utils
# --------------------------
Expand All @@ -48,4 +51,4 @@ dynamo.admin:
export PORT="4005" && \
npx dynamodb-admin

.PHONY: test sec errcheck staticcheck format lint-all lint build test dynamo.admin
.PHONY: dev test sec errcheck staticcheck format lint-all lint build build-openapi dynamo.admin
160 changes: 160 additions & 0 deletions backend/api/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
components:
schemas:
ErrorDetail:
additionalProperties: false
properties:
location:
description: Where the error occurred, e.g. 'body.items[3].tags' or 'path.thing-id'
type: string
message:
description: Error message text
type: string
value:
description: The value at the given location
type: object
ErrorModel:
additionalProperties: false
properties:
$schema:
description: A URL to the JSON Schema for this object.
examples:
- http://localhost:6500/api/v1/schemas/ErrorModel.json
format: uri
readOnly: true
type: string
detail:
description: A human-readable explanation specific to this occurrence of the problem.
examples:
- Property foo is required but is missing.
type: string
errors:
description: Optional list of individual error details
items:
$ref: "#/components/schemas/ErrorDetail"
type: array
instance:
description: A URI reference that identifies the specific occurrence of the problem.
examples:
- https://example.com/error-log/abc123
format: uri
type: string
status:
description: HTTP status code
examples:
- 400
format: int64
type: integer
title:
description: A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
examples:
- Bad Request
type: string
type:
default: about:blank
description: A URI reference to human-readable documentation for the error.
examples:
- https://example.com/errors/example
format: uri
type: string
type: object
GreetingOutput3Body:
additionalProperties: false
properties:
$schema:
description: A URL to the JSON Schema for this object.
examples:
- http://localhost:6500/api/v1/schemas/GreetingOutput3Body.json
format: uri
readOnly: true
type: string
message:
description: Greeting message
examples:
- Hello, world!
type: string
required:
- message
type: object
HealthCheckParams2Body:
additionalProperties: false
properties:
$schema:
description: A URL to the JSON Schema for this object.
examples:
- http://localhost:6500/api/v1/schemas/HealthCheckParams2Body.json
format: uri
readOnly: true
type: string
message:
description: Greeting message
examples:
- Hello, world!
type: string
required:
- message
type: object
securitySchemes:
bearer:
bearerFormat: JWT
scheme: bearer
type: http
info:
title: TinyURL
version: 1.0.0
openapi: 3.1.0
paths:
/greeting/{name}:
get:
description: Get a greeting for a person by name.
operationId: get-greeting
parameters:
- description: Name to greet
example: world
in: path
name: name
required: true
schema:
description: Name to greet
examples:
- world
maxLength: 30
type: string
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/GreetingOutput3Body"
description: OK
default:
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ErrorModel"
description: Error
summary: Get a greeting
tags:
- Greetings
/health:
get:
description: Check the health of the service.
operationId: health
responses:
"200":
content:
application/json:
schema:
$ref: "#/components/schemas/HealthCheckParams2Body"
description: OK
default:
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ErrorModel"
description: Error
summary: Health Check
tags:
- Greetings
servers:
- url: http://localhost:6500/api/v1

38 changes: 22 additions & 16 deletions backend/cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ type Options struct {
Port int `doc:"Port to listen on." short:"p" default:"8888"`
}

// /api/v1/openapi.yaml
// initHuma: humaのconfigを初期化
func initHuma() huma.Config {
config := huma.DefaultConfig(configs.OpenAPITitle, configs.OpenAPIVersion)
// Openapiのserver設定
config.Servers = []*huma.Server{
{URL: "http://localhost:6500/api/v1"},
}

config.Components.SecuritySchemes = map[string]*huma.SecurityScheme{
"bearer": {
Type: "http",
Scheme: "bearer",
BearerFormat: "JWT",
},
}
config.DocsPath = "/docs"
return config
}

// publicにわける
// user(ログイン必須)
// private(管理者)
Expand All @@ -38,25 +58,11 @@ func main() {
e := echo.New()
// configを初期化
configs.NewAppEnvironment()
config := huma.DefaultConfig(configs.OpenAPITitle, configs.OpenAPIVersion)
// Openapiのserver設定
config.Servers = []*huma.Server{
{URL: "http://localhost:6500/api/v1"},
}

config.Components.SecuritySchemes = map[string]*huma.SecurityScheme{
"bearer": {
Type: "http",
Scheme: "bearer",
BearerFormat: "JWT",
},
}
config.DocsPath = "/docs"
// ミドルウェアを適用(すべてのリクエストに対して)
middleware.CustomMiddleware(e)
// /api/v1/openapi.yaml

// これgroup化したやつをnewUserRouterに渡す必要かも
api = humaecho.NewWithGroup(e, e.Group("/api/v1"), config)
api = humaecho.NewWithGroup(e, e.Group("/api/v1"), initHuma())
router.NewPublicRouter(api)

// 未定義のルート用のキャッチオールハンドラ
Expand Down
7 changes: 4 additions & 3 deletions backend/configs/constructor.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package configs

const (
ApplicationPort = ":6500"
OpenAPITitle = "TinyURL"
OpenAPIVersion = "1.0.0"
ApplicationPort = ":6500"
OpenAPITitle = "TinyURL API"
OpenAPIVersion = "1.0.0"
OpenAPIServerPath = "http://localhost:6500/api/v1"
)
52 changes: 24 additions & 28 deletions backend/internal/rest/router/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ package router

import (
"context"
"errors"
"fmt"
"net/http"

"github.com/danielgtaylor/huma/v2"
"github.com/labstack/echo/v4"
Router "github.com/naohito-T/tinyurl/backend/configs"
"github.com/naohito-T/tinyurl/backend/internal/infrastructures/slog"
// "github.com/naohito-T/tinyurl/backend/internal/rest/container"
)

Expand Down Expand Up @@ -48,17 +45,16 @@ func NewPublicRouter(app huma.API) {
OperationID: "health",
Method: http.MethodGet,
Path: Router.Health,
Summary: "Get a greeting",
Description: "Get a greeting for a person by name.",
Summary: "Health Check",
Description: "Check the health of the service.",
Tags: []string{"Greetings"},
}, func(_ context.Context, _ *HealthCheckParams) (*HealthCheckParams2, error) {
resp := &HealthCheckParams2{Body: struct {
Message string `json:"message" example:"Hello, world!" doc:"Greeting message"`
}{Message: "ok3"}}
}{Message: "ok"}}
return resp, nil
})

// Register GET /greeting/{name}
huma.Register(app, huma.Operation{
OperationID: "get-greeting",
Method: http.MethodGet,
Expand All @@ -80,26 +76,26 @@ func NewPublicRouter(app huma.API) {

}

func hello(c echo.Context) error {
// {"time":"2024-04-14T02:16:18.08145333Z","level":"INFO","msg":"Hello, World!"}
slog.NewLogger().Info("Hello, World!")
if err := isValid("hello"); err != nil {
return err
}
return c.String(http.StatusOK, "Hello, World 2!")
}
// func hello(c echo.Context) error {
// // {"time":"2024-04-14T02:16:18.08145333Z","level":"INFO","msg":"Hello, World!"}
// slog.NewLogger().Info("Hello, World!")
// if err := isValid("hello"); err != nil {
// return err
// }
// return c.String(http.StatusOK, "Hello, World 2!")
// }

func health(c echo.Context) error {
println("Hello, World!")
if err := isValid("hello"); err != nil {
return err
}
return c.String(http.StatusOK, "Hello, World!")
}
// func health(c echo.Context) error {
// println("Hello, World!")
// if err := isValid("hello"); err != nil {
// return err
// }
// return c.String(http.StatusOK, "Hello, World!")
// }

func isValid(txt string) error {
if txt == "" {
return errors.New("Invalid")
}
return nil
}
// func isValid(txt string) error {
// if txt == "" {
// return errors.New("Invalid")
// }
// return nil
// }

0 comments on commit cbdd2e8

Please sign in to comment.