Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alimy/mir

Mir is a toolkit for register method handler to http engine router(eg: gin,echo,iris,mux,httprouter) use struct tag info.
https://github.com/alimy/mir

echo gin go go-chi go-mir golang hertz httprouter iris macaron mux web

Last synced: 27 days ago
JSON representation

Mir is a toolkit for register method handler to http engine router(eg: gin,echo,iris,mux,httprouter) use struct tag info.

Awesome Lists containing this project

README

        

[![Go](https://github.com/alimy/mir/actions/workflows/go.yml/badge.svg)](https://github.com/alimy/mir/actions/workflows/go.yml)
[![GoDoc](https://godoc.org/github.com/alimy/mir?status.svg)](https://pkg.go.dev/github.com/alimy/mir/v4)
[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?logo=sourcegraph)](https://sourcegraph.com/github.com/alimy/mir)



Logo

Mir


A cool help tool to develop RESTful API.


Mir is a toolkit to develop RESTful API backend service like develop service of gRPC. It adapt some HTTP framework sush as [Gin](https://github.com/gin-gonic/gin), [Chi](https://github.com/go-chi/chi), [Hertz](https://github.com/cloudwego/hertz), [Echo](https://github.com/labstack/echo), [Iris](https://github.com/kataras/iris), [Fiber](https://github.com/gofiber/fiber), [Macaron](https://github.com/go-macaron/macaron), [Mux](https://github.com/gorilla/mux), [httprouter](https://github.com/julienschmidt/httprouter)。







### Tutorials
* Generate a simple template project
```bash
% go install github.com/alimy/mir/mirc/v4@latest
% mirc new -h
create template project

Usage:
mirc new [flags]

Flags:
-d, --dst string genereted destination target directory (default ".")
-h, --help help for new
--mir string mir replace package name or place
-p, --pkg string project's package name (default "github.com/alimy/mir-example")
-s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin")

% mirc new -d example
% tree example
example
.
|-- Makefile
|-- README.md
|-- go.mod
|-- go.sum
|-- main.go
|-- mirc
| |-- auto
| | `-- api
| | |-- site.go
| | |-- v1
| | | `-- site.go
| | `-- v2
| | `-- site.go
| |-- gen.go
| `-- routes
| |-- site.go
| |-- v1
| | `-- site.go
| `-- v2
| `-- site.go
`-- servants
|-- core.go
|-- servants.go
|-- site.go
|-- site_v1.go
`-- site_v2.go

% cd example
% make generate
% make run
```

* RESTful API define:
```go
// file: mirc/routes.go

package routes

import (
. "github.com/alimy/mir/v4"
. "github.com/alimy/mir/v4/engine"
)

func init() {
AddEntry(new(User))
}

type LoginReq struct {
Name string `json:"name"`
Passwd string `json:"passwd"`
}

type LoginResp struct {
JwtToken string `json:"jwt_token"`
}

// User user interface info
type User struct {
Chain Chain `mir:"-"`
Group Group `mir:"v1"`
Login func(Post, LoginReq) LoginResp `mir:"/login/"`
Logout func(Post) `mir:"/logout/"`
}
```

* Stub source code generatee automatic:
```go
// file: mirc/auto/api/routes.go

// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0

package routes

import (
"net/http"

"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)

type _binding_ interface {
Bind(*gin.Context) mir.Error
}

type _render_ interface {
Render(*gin.Context)
}

type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}

type LoginReq struct {
Name string `json:"name"`
Passwd string `json:"passwd"`
}

type LoginResp struct {
JwtToken string `json:"jwt_token"`
}

type User interface {
_default_

// Chain provide handlers chain for gin
Chain() gin.HandlersChain

Login(*gin.Context, *LoginReq) (*LoginResp, mir.Error)
Logout(*gin.Context) mir.Error

mustEmbedUnimplementedUserServant()
}

// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}

// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)

// register routes info to router
router.Handle("POST", "/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
s.Render(c, resp, err)
})
router.Handle("POST", "/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}

r.Render(c, nil, s.Logout(c))
})
}

func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}

func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}

func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}

func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
```

* API interface implement:
```go
// file: servants/user.go

package servants

import (
"github.com/alimy/mir-example/v4/mirc/auto/api"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)

type baseSrv struct{}

func (baseSrv) Bind(c *gin.Context, obj any) mir.Error {
if err := c.ShouldBind(obj); err != nil {
mir.NewError(http.StatusBadRequest, err)
}
return nil
}

func (baseSrv) Render(c *gin.Context, data any, err mir.Error) {
if err == nil {
c.JSON(http.StatusOK, data)
} else {
c.JSON(err.StatusCode(), err.Error())
}
}

type userSrv struct {
baseSrv

api.UnimplementedUserServant
}

func newUserSrv() api.Site {
return &userSrv{}
}
```

* Service register:
```go
// file: servants/servants.go

package servants

import (
"github.com/alimy/mir-example/v4/mirc/auto/api"
"github.com/gin-gonic/gin"
)

// RegisterServants register all the servants to gin.Engine
func RegisterServants(e *gin.Engine) {
api.RegisterUserServant(e, newUserSrv())

// TODO: some other servant to register
}
```

* App start:
```go
// file: main.go

package main

import (
"log"

"github.com/alimy/mir-example/v4/servants"
"github.com/gin-gonic/gin"
)

func main() {
e := gin.Default()

// register servants to gin
servants.RegisterServants(e)

// start servant service
if err := e.Run(); err != nil {
log.Fatal(err)
}
}
```

### Projects that used [go-mir](https://github.com/alimy/mir)
* [examples](examples) - a demo example to describe how to use [Mir](https://github.com/alimy/mir) to develop RESTful API backend service quickly.
* [paopao-ce](https://github.com/rocboss/paopao-ce/tree/dev) - A artistic "twitter like" community built on gin+zinc+vue+ts.