The User API Gateway is created
CD to FoodGuides directory. Create an API folder
mkdir -p usermanage/api && cd usermanage/api
Copy the code
Create the user.api file
goctl api -o user.api
Copy the code
Defining API services
info(
title: // UserApi
desc: // User service related apis
)
type LoginRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
type LoginResponse struct {
UserReply
}
type RegisterRequest struct {
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
}
type RegisterResponse struct {
UserReply
}
type UserinfoRequest struct {
Userid string `json:"userid"`
Token string `json:"token"`
}
type UserinfoResponse struct {
UserReply
}
type UserReply {
Id int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
JwtToken
}
type JwtToken {
AccessToken string `json:"accessToken,omitempty"`
AccessExpire int64 `json:"accessExpire,omitempty"`
RefreshAfter int64 `json:"refreshAfter,omitempty"`
}
service user-api {
@handler Login // User login
post /users/login(LoginRequest) returns(LoginResponse)
@handler Register // User registration
post /users/register(RegisterRequest) returns(RegisterResponse)
@handler UserInfo // User information
post /users/userinfo(UserinfoRequest) returns(UserinfoResponse)
}
Copy the code
We defined three user-apis: Login Register UserInfo
Generate the User-API service
goctl api go -api user.api -dir .
Copy the code
Check out the API directory
➜ API git tree. (master) ✗ ├ ─ ─ etc │ └ ─ ─ the user - API. Yaml ├ ─ ─ internal │ ├ ─ ─ the config │ │ └ ─ ─ the config.go│ ├─ Finger Exercises ─ Finger Exercises.go│ │ ├ ─ ─ registerhandler.go│ │ ├ ─ ─ routes.go│ │ └ ─ ─ userinfohandler.go│ ├─ Logic │ ├─ LoginLogic.go│ │ ├ ─ ─ registerlogic.go│ │ └ ─ ─ userinfologic.go│ ├── │ ├─ ├─ ├─go│ ├ ─ garbage ─ garbagego├ ─ ─ user. API └ ─ ─ the user.go
Copy the code
To start the service, note that before starting the service, you need to make sure that the ningxi-compose used in the previous article is up and running.
go run user.go -f etc/user-api.yaml
Copy the code
Understand how services run
The Goctl tool helps you create API services quickly and easily. But without an understanding of how API services work, it can be confusing to look at the project structure.
api/etc
Under theuser-api.yaml
File. The file is configuredapi
Variables required by the service, such as the service nameName
, interface addressHost
, port number,Port
Information such as,MySQL
,Redis
,rpc
And so the configuration is also written here.api
Under theuser.api
File. The file definesapi
The interface information provided by the service and subsequent interface additions are also handled here. And then callgoctl
Regenerate the service.api
Under theuser.go
File. The file isapi
The entry file for the service, where it all starts.
Internal folder
The internal implementation code for the API service is placed under this folder.
Go file in internal/config. You will notice that the definition of this file is similar to that of user-api.yaml. Yes. The user-api.yaml entry file in the user.go method is parsed into a Config object. So their values correspond one to one.
The file of phones. go under internal or handler is configured. This file is the routing file of the API service, which defines the request mode of each interface, the interface path, and the method triggered by the interface. For example: the client request the http://localhost:8888/users/register in the post way, the API service will trigger RegisterHandler () method.
func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
engine.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/users/login",
Handler: LoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/users/register",
Handler: RegisterHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/users/userinfo",
Handler: UserInfoHandler(serverCtx),
},
},
)
}
Copy the code
Xxxhandler. go file under internal/handler. The implementation of each interface trigger method is written in this file.
func RegisterHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.RegisterRequest
iferr := httpx.Parse(r, &req); err ! =nil {
httpx.Error(w, err)
return
}
l := logic.NewRegisterLogic(r.Context(), ctx)
resp, err := l.Register(req)
iferr ! =nil {
httpx.Error(w, err)
} else {
httpx.OkJson(w, resp)
}
}
}
Copy the code
You can see that the RegisterHandler first parses the received parameters. We then call logic.newregisterLogic () and see that RegisterHandler is not the final implementation. The final business processing is actually in the various logic.go files in the Logic folder.
The xxxlogic.go file is stored in internal/logic. We will eventually call the corresponding RPC service in each logic implementation.
The servicecontext.go file in internal/ SVC. This file holds the CONFIG object for the API service and instantiates the objects for each RPC service. The SVC object is then passed from Handle to the Logic method. Finally, Logic is implemented through SVC objects when calling RPC services.
func (l *LoginLogic) Login(req types.LoginRequest) (*types.LoginResponse, error) {
resp,err := l.svcCtx.User.Login(l.ctx, &user.LoginRequest{ // The user RPC service is invoked via svcCtx
Email: req.Email,
Password: req.Password,
});
}
Copy the code
The types.go file under internal/types. This file defines the various constructs we declared in the User.api template file.
Call procedure carding
The following uses the login interface as an example.
user.go
Import file passyaml
Configuration file, instantiateconfig
Object.
var configFile = flag.String("f"."etc/user-api.yaml"."the config file")
func main(a) {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
}
Copy the code
instantiationServiceContext
object
ctx := svc.NewServiceContext(c)
Copy the code
CTX holds the Config object internally. The User RPX service is initialized. CTX then has the ability to call RPC services.
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
User: userclient.NewUser(zrpc.MustNewClient(c.User)),
}
}
Copy the code
instantiationServer
Object.
server := rest.MustNewServer(c.RestConf)
Copy the code
Routing implementation, noticectx
Be passed to thehandlers
The internal.
handler.RegisterHandlers(server, ctx)
Copy the code
api
Service runs
server.Start()
Copy the code
When the client invokes the login interface. The LoginHandler method is triggered
func LoginHandler(ctx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewLoginLogic(r.Context(), ctx)
resp, err := l.Login(req)
}
Copy the code
LoginHandler then calls the LoginLogic method
func (l *LoginLogic) Login(req types.LoginRequest) (*types.LoginResponse, error) {
resp,err := l.svcCtx.User.Login(l.ctx, &user.LoginRequest{
Email: req.Email,
Password: req.Password,
});
}
Copy the code
In the Login. We invoked the Login method in the User RPC service via l.svcctx.
After processing the data, the interface responds layer by layer, and finally completes the invocation of the client interface.
Along the way, a call to RPC comes up. The above example has not yet appeared, you will read the text after the next, and then understand the call process, to be able to understand better.
Previous post go-Zero Tutorial: Service partitioning and Project Creation
The next go-Zero tutorial — User Rpc-Login