grpc-gatewayã§Metadataã«è©°ããã¨ã©ã¼ã®å 容ãJSONã«è©°ãã¦RESTã¯ã©ã¤ã¢ã³ãã«è¿ããã
å¼ãç¶ãgRPCã®è©±ã
gRPCã§ã¨ã©ã¼ãã¯ã©ã¤ã¢ã³ãã«è¿ãããå ´åãé常ã ã¨ã¹ãã¼ã¿ã¹ã³ã¼ãã¨ã¨ã©ã¼ã¡ãã»ã¼ã¸ããè¿ããªããä¾ãã°ã¢ããªã±ã¼ã·ã§ã³ã¬ãã«ã®ããªãã¼ã·ã§ã³ã¨ã©ã¼ã¿ãããªãã®ãè¿ãããæãã¡ã«ã«ãªããã®è³æã«ããã¨Metadataã«è©°ãã¦éãã¨è¯ããããã
gRPCãã¯ã©ã¤ã¢ã³ãã®ã¨ãã¯è©°ããMetadataãèªã¿åºãã°ãããã ãã©ãgrpc-gatewayã§RESTã®ã¯ã©ã¤ã¢ã³ãã«è¿ãæã«ã¯ã©ããããããã調ã¹ãã
grpc-gatewayã®ã¨ã©ã¼ãã³ããªã³ã°ãã«ã¹ã¿ãã¤ãºãã
å®ã¯GitHubã®wikiã« How to customize your gateway
ã¨ããã®ããã£ã¦ãããã«çµæ§è²ã
ã¨æ¸ããã¦ããã
How to customize your gateway · grpc-ecosystem/grpc-gateway Wiki · GitHub
ã§ãWikiãã辿ã£ãå ã«ããããã°ã«å®éã«çµæ§ä¸å¯§ã«ã¨ã©ã¼ã¬ã¹ãã³ã¹ã®ã«ã¹ã¿ãã¤ãºæ¹æ³ãä¹ã£ã¦ãã®ã§ããããåèã«ããã°ããã
fun run() error { runtime.HTTPError = CustomHTTPError // çç¥ } type errorBody struct { Error string `json:âerror"` ErrorDetails []ErrorDetail `json:âerrorDetailsâ` } type errorDetails struct { Field string `json:âfieldâ` Message string `json:âmessageâ` } // ããã«gRPCã®MetadataãerrorBodyã®ãããªæ§é ã«å¤æããã¯ã©ã¤ã¢ã³ãã«è¿ãããã®ã«ã¹ã¿ã ãã³ãã©ã¼ func CustomHTTPError(ctx context.Context, _ *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, _ *http.Request, err error) { const fallback = `{"error": "failed to marshal error message"}` w.Header().Set("Content-type", marshaler.ContentType()) w.WriteHeader(runtime.HTTPStatusFromCode(grpc.Code(err))) eb := errorBody{ Err: grpc.ErrorDesc(err), } md, _ := runtime.ServerMetadataFromContext(ctx) for k, v := range md.TrailerMD { eb.ErrorDetails = append(eb.ErrorDetails, errorDetail{ Field: strings.TrimSuffix(k, "-bin"), // ãã¤ããªã§å¸°ã£ã¦ããæååã¯-binã®prefixãã¤ãã®ã§ãã¯ã©ã¤ã¢ã³ããæ±ããããããæ¶ã Message: v[0], // ãµã¼ãã¼å´ã§ã¯æååã¨ãã¦ããå ¥ãã¦ããªãããä½æ ãArrayã§å ¥ã£ã¦ããã®æåã®ãã®ã ãåå¾ãã }) } jErr := json.NewEncoder(w).Encode(eb) if jErr != nil { w.Write([]byte(fallback)) } }
Goæ¸ãã®ä¹ ãã¶ãããã¦ãããªæãã§ããã£ããå ¨ç¶èªä¿¡ãªããã©ãä¸å¿ãããããã¨ã¯å®ç¾ã§ããã