Skip to content
This repository has been archived by the owner on Oct 27, 2023. It is now read-only.

Commit

Permalink
add gin plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
guoliangcao committed Jul 18, 2021
1 parent 0eedf6e commit 0365ef9
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@

# Dependency directories (remove the comment below to include it)
# vendor/

.vscode
52 changes: 52 additions & 0 deletions examples/simple/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"context"
"fmt"
"log"

"github.com/gin-gonic/gin"
kgin "github.com/go-kratos/gin"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport"
"github.com/go-kratos/kratos/v2/transport/http"
)

func customMiddleware(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
if tr, ok := transport.FromServerContext(ctx); ok {
fmt.Println("operation:", tr.Operation())
}
reply, err = handler(ctx, req)
return
}
}

func main() {
router := gin.Default()
router.Use(kgin.Middlewares(recovery.Recovery(), customMiddleware))
router.GET("/helloworld/:name", func(ctx *gin.Context) {
name := ctx.Param("name")
if name == "error" {
kgin.Error(ctx, errors.Unauthorized("auth_error", "no authentication"))
} else {
ctx.JSON(200, map[string]string{"welcome": name})
}
})

httpSrv := http.NewServer(http.Address(":8000"))
httpSrv.HandlePrefix("/", router)

app := kratos.New(
kratos.Name("gin"),
kratos.Server(
httpSrv,
),
)
if err := app.Run(); err != nil {
log.Fatal(err)
}
}
92 changes: 92 additions & 0 deletions gin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package gin

import (
"context"
"net/http"
"strings"

"github.com/gin-gonic/gin"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/middleware"
thttp "github.com/go-kratos/kratos/v2/transport/http"
)

const (
baseContentType = "application"
)

type errorRender struct {
body []byte
contentType string
}

// Render (JSON) writes data with custom ContentType.
func (er *errorRender) Render(w http.ResponseWriter) error {
_, err := w.Write(er.body)
return err
}

// WriteContentType (JSON) writes JSON ContentType.
func (er *errorRender) WriteContentType(w http.ResponseWriter) {
w.Header().Set("Content-Type", er.contentType)

}

// Error encodes the object to the HTTP response.
func Error(c *gin.Context, err error) {
if err == nil {
c.Status(http.StatusOK)
return
}
codec, _ := thttp.CodecForRequest(c.Request, "Accept")
se := errors.FromError(err)
body, err := codec.Marshal(se)
if err != nil {
c.Status(http.StatusInternalServerError)
return
}
contentType := codec.Name()
code := int(se.Code)
c.Render(code, &errorRender{body: body, contentType: contentType})
return
}

// ContentType returns the content-type with base prefix.
func ContentType(subtype string) string {
return strings.Join([]string{baseContentType, subtype}, "/")
}

// Middlewares return middlewares wrapper
func Middlewares(m ...middleware.Middleware) gin.HandlerFunc {
chain := middleware.Chain(m...)
return func(c *gin.Context) {
next := func(ctx context.Context, req interface{}) (interface{}, error) {
c.Next()
var err error
if c.Writer.Status() >= 400 {
err = errors.Errorf(c.Writer.Status(), errors.UnknownReason, errors.UnknownReason)
}
return c.Writer, err
}
next = chain(next)
ctx := NewGinContext(c.Request.Context(), c)
c.Request = c.Request.WithContext(ctx)
if ginCtx, ok := FromGinContext(ctx); ok {
thttp.SetOperation(ctx, ginCtx.FullPath())
}
next(c.Request.Context(), c.Request)
}
}

type ginKey struct{}

// NewGinContext returns a new Context that carries gin.Context value.
func NewGinContext(ctx context.Context, c *gin.Context) context.Context {
return context.WithValue(ctx, ginKey{}, c)
}

// FromGinContext returns the gin.Context value stored in ctx, if any.
func FromGinContext(ctx context.Context) (c *gin.Context, ok bool) {
c, ok = ctx.Value(ginKey{}).(*gin.Context)
return
}
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/go-kratos/gin

go 1.15

require (
github.com/gin-gonic/gin v1.7.2
github.com/go-kratos/kratos/v2 v2.0.0
)
Loading

0 comments on commit 0365ef9

Please sign in to comment.