Skip to content

Commit

Permalink
refactor: improve admin router (arana-db#407)
Browse files Browse the repository at this point in the history
  • Loading branch information
jjeffcaii authored Sep 11, 2022
1 parent 8e1e40e commit 6a00a09
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 227 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ services:
depends_on:
- mysql
- etcd
restart: on-failure

arana-admin:
container_name: arana-admin
Expand All @@ -79,6 +80,7 @@ services:
- ./conf/bootstrap.docker.yaml:/etc/arana/bootstrap.yaml:ro
depends_on:
- etcd
restart: on-failure

networks:
local:
Expand Down
2 changes: 0 additions & 2 deletions pkg/admin/admin.api.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
Expand All @@ -13,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

openapi: 3.0.3
info:
Expand Down
65 changes: 54 additions & 11 deletions pkg/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"errors"
"io"
"net"
"net/http"
"os"
"strings"
)
Expand All @@ -36,6 +35,7 @@ import (
)

import (
"github.com/arana-db/arana/pkg/admin/exception"
"github.com/arana-db/arana/pkg/boot"
"github.com/arana-db/arana/pkg/constants"
)
Expand All @@ -46,7 +46,17 @@ var NotFoundError = errors.New("resource not found")

var _hooks []Hook

type Hook func(router gin.IRoutes)
type Hook func(Router)

type Handler func(*gin.Context) error

type Router interface {
GET(string, Handler)
POST(string, Handler)
DELETE(string, Handler)
PATCH(string, Handler)
PUT(string, Handler)
}

func Register(hook Hook) {
_hooks = append(_hooks, hook)
Expand Down Expand Up @@ -100,17 +110,10 @@ func (srv *Server) Listen(addr string) error {
})
srv.engine.Use(gin.Logger())
srv.engine.Use(gin.Recovery())
srv.engine.Use(
ErrorHandler(
Map(NotFoundError).
ToResponse(func(c *gin.Context, err error) {
c.Status(http.StatusNotFound)
_, _ = c.Writer.WriteString(err.Error())
}),
))
srv.engine.Use(CORSMiddleware())

for _, hook := range _hooks {
hook(srv.engine)
hook((*myRouter)(srv.engine))
}

if srv.l, err = c.Listen(context.Background(), "tcp", addr); err != nil {
Expand All @@ -124,3 +127,43 @@ func GetService(c *gin.Context) Service {
v, _ := c.Get(K)
return v.(Service)
}

type myRouter gin.Engine

func (w *myRouter) GET(s string, handler Handler) {
(*gin.Engine)(w).GET(s, w.wrapper(handler))
}

func (w *myRouter) POST(s string, handler Handler) {
(*gin.Engine)(w).POST(s, w.wrapper(handler))
}

func (w *myRouter) DELETE(s string, handler Handler) {
(*gin.Engine)(w).DELETE(s, w.wrapper(handler))
}

func (w *myRouter) PATCH(s string, handler Handler) {
(*gin.Engine)(w).PATCH(s, w.wrapper(handler))
}

func (w *myRouter) PUT(s string, handler Handler) {
(*gin.Engine)(w).PUT(s, w.wrapper(handler))
}

func (w *myRouter) wrapper(handler Handler) gin.HandlerFunc {
return func(c *gin.Context) {
err := handler(c)
if err == nil {
return
}
switch e := err.(type) {
case exception.APIException:
c.JSON(e.Code.HttpStatus(), e)
case *exception.APIException:
c.JSON(e.Code.HttpStatus(), e)
default:
ee := exception.Wrap(exception.CodeUnknownError, e)
c.JSON(ee.Code.HttpStatus(), ee)
}
}
}
38 changes: 38 additions & 0 deletions pkg/admin/cors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package admin

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

func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, PATCH, DELETE")

if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}

c.Next()
}
}
70 changes: 70 additions & 0 deletions pkg/admin/exception/exception.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package exception

import (
"fmt"
)

const (
CodeServerError Code = 1000 + iota
CodeNotFound
CodeInvalidParams
CodeAuth
CodeUnknownError
)

var _httpStatus = map[Code]int{
CodeNotFound: 404,
CodeInvalidParams: 400,
CodeAuth: 401,
CodeServerError: 500,
}

type Code uint16

func (ec Code) HttpStatus() int {
hc, ok := _httpStatus[ec]
if ok {
return hc
}
return 500
}

type APIException struct {
Code Code `json:"code"`
Message string `json:"message"`
}

func (ae APIException) Error() string {
return fmt.Sprintf("ERR-%05d: %s", ae.Code, ae.Message)
}

func New(code Code, format string, args ...interface{}) APIException {
return APIException{
Code: code,
Message: fmt.Sprintf(format, args...),
}
}

func Wrap(code Code, err error) APIException {
return APIException{
Code: code,
Message: err.Error(),
}
}
81 changes: 0 additions & 81 deletions pkg/admin/middleware.go

This file was deleted.

Loading

0 comments on commit 6a00a09

Please sign in to comment.