github.com/alimy/mir/v4@v4.1.0/README-en.md (about) 1 [](https://github.com/alimy/mir/actions/workflows/go.yml) 2 [](https://pkg.go.dev/github.com/alimy/mir/v4) 3 [](https://sourcegraph.com/github.com/alimy/mir) 4 5 <div align="center"> 6 <a href="https://github.com/alimy/mir"> 7 <img src="https://alimy.me/mir/images/mir-logo.png" alt="Logo" width="240" height="240"> 8 </a> 9 10 <h3 align="center">Mir</h3> 11 12 <p align="center"> 13 A cool help tool to develop RESTful API. 14 </p> 15 </div> 16 17 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)。 18 19 <div align="center"> 20 <a href="https://github.com/alimy/mir"> 21 <img src="https://alimy.me/mir/images/mir-arc.png"> 22 </a> 23 </div> 24 25 ### Tutorials 26 * Generate a simple template project 27 ```bash 28 % go install github.com/alimy/mir/mirc/v4@latest 29 % mirc new -h 30 create template project 31 32 Usage: 33 mirc new [flags] 34 35 Flags: 36 -d, --dst string genereted destination target directory (default ".") 37 -h, --help help for new 38 --mir string mir replace package name or place 39 -p, --pkg string project's package name (default "github.com/alimy/mir-example") 40 -s, --style string generated engine style eg: gin,chi,mux,hertz,echo,iris,fiber,fiber-v2,macaron,httprouter (default "gin") 41 42 % mirc new -d example 43 % tree example 44 example 45 . 46 |-- Makefile 47 |-- README.md 48 |-- go.mod 49 |-- go.sum 50 |-- main.go 51 |-- mirc 52 | |-- auto 53 | | `-- api 54 | | |-- site.go 55 | | |-- v1 56 | | | `-- site.go 57 | | `-- v2 58 | | `-- site.go 59 | |-- gen.go 60 | `-- routes 61 | |-- site.go 62 | |-- v1 63 | | `-- site.go 64 | `-- v2 65 | `-- site.go 66 `-- servants 67 |-- core.go 68 |-- servants.go 69 |-- site.go 70 |-- site_v1.go 71 `-- site_v2.go 72 73 % cd example 74 % make generate 75 % make run 76 ``` 77 78 * RESTful API define: 79 ```go 80 // file: mirc/routes.go 81 82 package routes 83 84 import ( 85 . "github.com/alimy/mir/v4" 86 . "github.com/alimy/mir/v4/engine" 87 ) 88 89 func init() { 90 AddEntry(new(User)) 91 } 92 93 type LoginReq struct { 94 Name string `json:"name"` 95 Passwd string `json:"passwd"` 96 } 97 98 type LoginResp struct { 99 JwtToken string `json:"jwt_token"` 100 } 101 102 // User user interface info 103 type User struct { 104 Chain Chain `mir:"-"` 105 Group Group `mir:"v1"` 106 Login func(Post, LoginReq) LoginResp `mir:"/login/"` 107 Logout func(Post) `mir:"/logout/"` 108 } 109 ``` 110 111 * Stub source code generatee automatic: 112 ```go 113 // file: mirc/auto/api/routes.go 114 115 // Code generated by go-mir. DO NOT EDIT. 116 // versions: 117 // - mir v4.0.0 118 119 package routes 120 121 import ( 122 "net/http" 123 124 "github.com/alimy/mir/v4" 125 "github.com/gin-gonic/gin" 126 ) 127 128 type _binding_ interface { 129 Bind(*gin.Context) mir.Error 130 } 131 132 type _render_ interface { 133 Render(*gin.Context) 134 } 135 136 type _default_ interface { 137 Bind(*gin.Context, any) mir.Error 138 Render(*gin.Context, any, mir.Error) 139 } 140 141 type LoginReq struct { 142 Name string `json:"name"` 143 Passwd string `json:"passwd"` 144 } 145 146 type LoginResp struct { 147 JwtToken string `json:"jwt_token"` 148 } 149 150 type User interface { 151 _default_ 152 153 // Chain provide handlers chain for gin 154 Chain() gin.HandlersChain 155 156 Login(*gin.Context, *LoginReq) (*LoginResp, mir.Error) 157 Logout(*gin.Context) mir.Error 158 159 mustEmbedUnimplementedUserServant() 160 } 161 162 // UnimplementedUserServant can be embedded to have forward compatible implementations. 163 type UnimplementedUserServant struct { 164 } 165 166 // RegisterUserServant register User servant to gin 167 func RegisterUserServant(e *gin.Engine, s User) { 168 router := e.Group("v1") 169 // use chain for router 170 middlewares := s.Chain() 171 router.Use(middlewares...) 172 173 // register routes info to router 174 router.Handle("POST", "/login/", func(c *gin.Context) { 175 select { 176 case <-c.Request.Context().Done(): 177 return 178 default: 179 } 180 req := new(LoginReq) 181 if err := s.Bind(c, req); err != nil { 182 s.Render(c, nil, err) 183 return 184 } 185 resp, err := s.Login(req) 186 s.Render(c, resp, err) 187 }) 188 router.Handle("POST", "/logout/", func(c *gin.Context) { 189 select { 190 case <-c.Request.Context().Done(): 191 return 192 default: 193 } 194 195 r.Render(c, nil, s.Logout(c)) 196 }) 197 } 198 199 func (UnimplementedUserServant) Chain() gin.HandlersChain { 200 return nil 201 } 202 203 func (UnimplementedUserServant) Login(c *gin.Context, req *LoginReq) (*LoginResp, mir.Error) { 204 return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) 205 } 206 207 func (UnimplementedUserServant) Logout(c *gin.Context) mir.Error { 208 return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented)) 209 } 210 211 func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {} 212 ``` 213 214 * API interface implement: 215 ```go 216 // file: servants/user.go 217 218 package servants 219 220 import ( 221 "github.com/alimy/mir-example/v4/mirc/auto/api" 222 "github.com/alimy/mir/v4" 223 "github.com/gin-gonic/gin" 224 ) 225 226 type baseSrv struct{} 227 228 func (baseSrv) Bind(c *gin.Context, obj any) mir.Error { 229 if err := c.ShouldBind(obj); err != nil { 230 mir.NewError(http.StatusBadRequest, err) 231 } 232 return nil 233 } 234 235 func (baseSrv) Render(c *gin.Context, data any, err mir.Error) { 236 if err == nil { 237 c.JSON(http.StatusOK, data) 238 } else { 239 c.JSON(err.StatusCode(), err.Error()) 240 } 241 } 242 243 type userSrv struct { 244 baseSrv 245 246 api.UnimplementedUserServant 247 } 248 249 func newUserSrv() api.Site { 250 return &userSrv{} 251 } 252 ``` 253 254 * Service register: 255 ```go 256 // file: servants/servants.go 257 258 package servants 259 260 import ( 261 "github.com/alimy/mir-example/v4/mirc/auto/api" 262 "github.com/gin-gonic/gin" 263 ) 264 265 // RegisterServants register all the servants to gin.Engine 266 func RegisterServants(e *gin.Engine) { 267 api.RegisterUserServant(e, newUserSrv()) 268 269 // TODO: some other servant to register 270 } 271 ``` 272 273 * App start: 274 ```go 275 // file: main.go 276 277 package main 278 279 import ( 280 "log" 281 282 "github.com/alimy/mir-example/v4/servants" 283 "github.com/gin-gonic/gin" 284 ) 285 286 func main() { 287 e := gin.Default() 288 289 // register servants to gin 290 servants.RegisterServants(e) 291 292 // start servant service 293 if err := e.Run(); err != nil { 294 log.Fatal(err) 295 } 296 } 297 ``` 298 299 ### Projects that used [go-mir](https://github.com/alimy/mir) 300 * [examples](examples) - a demo example to describe how to use [Mir](https://github.com/alimy/mir) to develop RESTful API backend service quickly. 301 * [paopao-ce](https://github.com/rocboss/paopao-ce/tree/dev) - A artistic "twitter like" community built on gin+zinc+vue+ts.