1.可以在客户端设置发送带有HTTP Headers的request
func main() {
client := haberdasher.NewHaberdasherProtobufClient("http://localhost:8080", &http.Client{})
header := make(http.Header)
header.Set("Twitch-Authorization", "uDRlDxQYbFVXarBvmTncBoWKcZKqrZTY")
header.Set("Twitch-Client-ID", "FrankerZ")
header.Set("Name", "pengjunjie")
// Attach the headers to a context
ctx := context.Background()
ctx, err := twirp.WithHTTPRequestHeaders(ctx, header)
if err != nil {
log.Printf("twirp error setting headers: %s", err)
return
}
hat, err := client.MakeHat(ctx, &haberdasher.Size{Inches: 12})
if err != nil {
fmt.Printf("oh no: %v", err)
os.Exit(1)
}
fmt.Printf("I have a nice new hat: %+v", hat)
}
分析:通过header.set(key,value)的方法来设自定义设置header中存储的数据,并通过WithHTTPRequestHeaders方法将header整合到context中,再将context作为接口的参数传到服务端
2.可以通过编写中间件来封装服务端
func main() {
server := &haberdasherserver.Server{} // implements Haberdasher interface
twirpHandler := haberdasher.NewHaberdasherServer(server, nil)
wrapped := WithUserAgent(twirpHandler)
http.ListenAndServe(":8080", wrapped)
}
func WithUserAgent(base http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ua := r.Header.Get("Name")
fmt.Println("server:" + ua)
ctx = context.WithValue(ctx, "name", ua)
r = r.WithContext(ctx)
base.ServeHTTP(w, r)
})
}
分析:服务端经过封装后,可以读取到header中的数据,并把读取的数据再一次整合到context,当调用接口时,会把context作为接口实现方法的参数传入
3.接口实现方法读取到context中的数据,并把处理后的结果返回给客户端
func (s *Server) MakeHat(ctx context.Context, size *pb.Size) (hat *pb.Hat, err error) {
ua := ctx.Value("name").(string)
log.Printf("name: %v", ua)
if size.Inches <= 0 {
return nil, twirp.InvalidArgumentError("inches", "I can't make a hat that small!")
}
return &pb.Hat{
Inches: size.Inches,
Color: []string{"white", "black", "brown", "red", "blue"}[rand.Intn(4)],
Name: []string{"bowler", "baseball cap", "top hat", "derby"}[rand.Intn(3)],
}, nil
}
4.测试