introduce
This article introduces how to design reasonable API error codes under the gorilla/mux framework through a complete example .
We will use rk-boot to start the gorilla/mux microservice .
Please visit the following address for the complete tutorial:
scope of consideration
A reasonable RPC error needs to consider the following aspects.
- Contains error codes, error messages
- Error messages are extensible
- Consider readability
- Parsability, that is, the user can parse the error code through the code and take effective action
- Avoid internal error benefits, e.g. Nil point error
Error code structure
{
"error":{
"code":500,
"status":"Internal Server Error",
"message":"Panic manually!",
"details":[]
}
}
Install
go get github.com/rookie-ninja/rk-boot/mux
quick start
With rk-boot , users can easily build gorilla/mux framework microservices. rk-boot integrates Panic capture and standard error types.
1. Create boot.yaml
The boot.yaml file describes the meta information of the gorilla/mux framework startup, and rk-boot starts gorilla/mux by reading boot.yaml .
---
mux:
- name: greeter
port: 8080
enabled: true
2. Create main.go
Make /v1/greeter return an error.
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"github.com/rookie-ninja/rk-boot"
"github.com/rookie-ninja/rk-boot/mux"
"github.com/rookie-ninja/rk-common/error"
"github.com/rookie-ninja/rk-mux/interceptor"
"net/http"
)
func main() {
// Create a new boot instance.
boot := rkboot.NewBoot()
// Register handler
entry := rkbootmux.GetMuxEntry("greeter")
entry.Router.NewRoute().Methods(http.MethodGet).Path("/v1/greeter").HandlerFunc(Greeter)
// Bootstrap
boot.Bootstrap(context.TODO())
boot.WaitForShutdownSig(context.TODO())
}
func Greeter(writer http.ResponseWriter, request *http.Request) {
err := rkerror.New(
rkerror.WithHttpCode(http.StatusAlreadyReported),
rkerror.WithMessage("Trigger manually!"),
rkerror.WithDetails("This is detail.", false, -1, 0.1))
rkmuxinter.WriteJson(writer, http.StatusAlreadyReported, err)
}
3. Start main.go
$ go run main.go
4. Verify
$ curl "localhost:8080/v1/greeter?name=rk-dev"
{
"error":{
"code":208,
"status":"Already Reported",
"message":"Trigger manually!",
"details":[
"This is detail.",
false,
-1,
0.1
]
}
}
Catch Panic (system crash)
We still use the demo code as an example.
In the RPC implementation, we try to crash the system to see how rk-boot automatically captures and returns what information to the user.
1. Modify main.go
// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"github.com/rookie-ninja/rk-boot"
"github.com/rookie-ninja/rk-boot/mux"
"net/http"
)
func main() {
// Create a new boot instance.
boot := rkboot.NewBoot()
// Register handler
entry := rkbootmux.GetMuxEntry("greeter")
entry.Router.NewRoute().Methods(http.MethodGet).Path("/v1/greeter").HandlerFunc(Greeter)
// Bootstrap
boot.Bootstrap(context.TODO())
boot.WaitForShutdownSig(context.TODO())
}
func Greeter(writer http.ResponseWriter, request *http.Request) {
panic("Panic manually!")
}
2. Verify
$ curl "localhost:8080/v1/greeter?name=rk-dev"
{
"error":{
"code":500,
"status":"Internal Server Error",
"message":"Panic manually!",
"details":[]
}
}
source code
Error handling in rk-boot is implemented in rk-common/error .
more examples
Please refer to: rk-demo for more examples.