diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 79deda0..6e81539 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -12,7 +12,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -135,50 +134,53 @@ func NewExampleServiceServer(svc ExampleService) WebRPCServer { } func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleService/Ping": - s.servePing(ctx, w, r) - return + handler = s.servePingJSON case "/rpc/ExampleService/Status": - s.serveStatus(ctx, w, r) - return + handler = s.serveStatusJSON case "/rpc/ExampleService/Version": - s.serveVersion(ctx, w, r) - return + handler = s.serveVersionJSON case "/rpc/ExampleService/GetUser": - s.serveGetUser(ctx, w, r) - return + handler = s.serveGetUserJSON case "/rpc/ExampleService/FindUser": - s.serveFindUser(ctx, w, r) - return + handler = s.serveFindUserJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] } + contentType = strings.TrimSpace(strings.ToLower(contentType)) - switch strings.TrimSpace(strings.ToLower(header[:i])) { + switch contentType { case "application/json": - s.servePingJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -186,21 +188,11 @@ func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWri } func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.ExampleService.Ping(ctx) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + // Call service method implementation. + err := s.ExampleService.Ping(ctx) if err != nil { RespondWithError(w, err) return @@ -211,50 +203,23 @@ func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.Respons w.Write([]byte("{}")) } -func (s *exampleServiceServer) serveStatus(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveStatusJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleServiceServer) serveStatusJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Status") - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.Status(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Status") + // Call service method implementation. + ret0, err := s.ExampleService.Status(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -263,50 +228,23 @@ func (s *exampleServiceServer) serveStatusJSON(ctx context.Context, w http.Respo w.Write(respBody) } -func (s *exampleServiceServer) serveVersion(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveVersionJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleServiceServer) serveVersionJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Version") - // Call service method - var ret0 *Version - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.Version(ctx) - }() - respContent := struct { - Ret0 *Version `json:"version"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Version") + // Call service method implementation. + ret0, err := s.ExampleService.Version(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *Version `json:"version"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -315,71 +253,39 @@ func (s *exampleServiceServer) serveVersionJSON(ctx context.Context, w http.Resp w.Write(respBody) } -func (s *exampleServiceServer) serveGetUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetUserJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) +func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + reqBody, err := io.ReadAll(r.Body) + if err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) + return } -} + defer r.Body.Close() -func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") - reqContent := struct { + reqPayload := struct { Arg0 map[string]string `json:"header"` Arg1 uint64 `json:"userID"` }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") + + // Call service method implementation. + ret0, ret1, err := s.ExampleService.GetUser(ctx, reqPayload.Arg0, reqPayload.Arg1) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) RespondWithError(w, err) return } - // Call service method - var ret0 uint32 - var ret1 *User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, ret1, err = s.ExampleService.GetUser(ctx, reqContent.Arg0, reqContent.Arg1) - }() - respContent := struct { + respPayload := struct { Ret0 uint32 `json:"code"` Ret1 *User `json:"user"` }{ret0, ret1} - + respBody, err := json.Marshal(respPayload) if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -388,70 +294,38 @@ func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.Resp w.Write(respBody) } -func (s *exampleServiceServer) serveFindUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveFindUserJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) +func (s *exampleServiceServer) serveFindUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + reqBody, err := io.ReadAll(r.Body) + if err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) + return } -} + defer r.Body.Close() -func (s *exampleServiceServer) serveFindUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "FindUser") - reqContent := struct { + reqPayload := struct { Arg0 *SearchFilter `json:"s"` }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) + ctx = context.WithValue(ctx, MethodNameCtxKey, "FindUser") + + // Call service method implementation. + ret0, ret1, err := s.ExampleService.FindUser(ctx, reqPayload.Arg0) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) RespondWithError(w, err) return } - // Call service method - var ret0 string - var ret1 *User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, ret1, err = s.ExampleService.FindUser(ctx, reqContent.Arg0) - }() - respContent := struct { + respPayload := struct { Ret0 string `json:"name"` Ret1 *User `json:"user"` }{ret0, ret1} - + respBody, err := json.Marshal(respPayload) if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -621,7 +495,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if resp.StatusCode != 200 { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read server error response body: %w", err)) } @@ -637,7 +511,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if out != nil { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read response body: %w", err)) } @@ -690,11 +564,8 @@ func (k *contextKey) String() string { } var ( - // For Client HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server - HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} + HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"} diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index 140517f..92ea34c 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -12,7 +12,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -105,44 +104,49 @@ func NewExampleAPIServer(svc ExampleAPI) WebRPCServer { } func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleAPI/Ping": - s.servePing(ctx, w, r) - return + handler = s.servePingJSON case "/rpc/ExampleAPI/Status": - s.serveStatus(ctx, w, r) - return + handler = s.serveStatusJSON case "/rpc/ExampleAPI/GetUsers": - s.serveGetUsers(ctx, w, r) - return + handler = s.serveGetUsersJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *exampleAPIServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] } + contentType = strings.TrimSpace(strings.ToLower(contentType)) - switch strings.TrimSpace(strings.ToLower(header[:i])) { + switch contentType { case "application/json": - s.servePingJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -150,21 +154,11 @@ func (s *exampleAPIServer) servePing(ctx context.Context, w http.ResponseWriter, } func (s *exampleAPIServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.ExampleAPI.Ping(ctx) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + // Call service method implementation. + err := s.ExampleAPI.Ping(ctx) if err != nil { RespondWithError(w, err) return @@ -175,50 +169,23 @@ func (s *exampleAPIServer) servePingJSON(ctx context.Context, w http.ResponseWri w.Write([]byte("{}")) } -func (s *exampleAPIServer) serveStatus(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveStatusJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleAPIServer) serveStatusJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Status") - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleAPI.Status(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Status") + // Call service method implementation. + ret0, err := s.ExampleAPI.Status(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -227,52 +194,24 @@ func (s *exampleAPIServer) serveStatusJSON(ctx context.Context, w http.ResponseW w.Write(respBody) } -func (s *exampleAPIServer) serveGetUsers(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetUsersJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleAPIServer) serveGetUsersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUsers") - // Call service method - var ret0 []*User - var ret1 *Location - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, ret1, err = s.ExampleAPI.GetUsers(ctx) - }() - respContent := struct { - Ret0 []*User `json:"users"` - Ret1 *Location `json:"location"` - }{ret0, ret1} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUsers") + // Call service method implementation. + ret0, ret1, err := s.ExampleAPI.GetUsers(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 []*User `json:"users"` + Ret1 *Location `json:"location"` + }{ret0, ret1} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -414,7 +353,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if resp.StatusCode != 200 { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read server error response body: %w", err)) } @@ -430,7 +369,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if out != nil { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read response body: %w", err)) } @@ -483,11 +422,8 @@ func (k *contextKey) String() string { } var ( - // For Client HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server - HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} + HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"} diff --git a/_examples/golang-nodejs/server/server.gen.go b/_examples/golang-nodejs/server/server.gen.go index 40b70eb..2d77015 100644 --- a/_examples/golang-nodejs/server/server.gen.go +++ b/_examples/golang-nodejs/server/server.gen.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strings" "time" @@ -121,41 +121,47 @@ func NewExampleServiceServer(svc ExampleService) WebRPCServer { } func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleService/Ping": - s.servePing(ctx, w, r) - return + handler = s.servePingJSON case "/rpc/ExampleService/GetUser": - s.serveGetUser(ctx, w, r) - return + handler = s.serveGetUserJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] } + contentType = strings.TrimSpace(strings.ToLower(contentType)) - switch strings.TrimSpace(strings.ToLower(header[:i])) { + switch contentType { case "application/json": - s.servePingJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -163,33 +169,22 @@ func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWri } func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.Ping(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + // Call service method implementation. + ret0, err := s.ExampleService.Ping(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -198,68 +193,37 @@ func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.Respons w.Write(respBody) } -func (s *exampleServiceServer) serveGetUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetUserJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") - reqContent := struct { - Arg0 *GetUserRequest `json:"req"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 *GetUserRequest `json:"req"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - var ret0 *User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.GetUser(ctx, reqContent.Arg0) - }() - respContent := struct { - Ret0 *User `json:"user"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") + // Call service method implementation. + ret0, err := s.ExampleService.GetUser(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *User `json:"user"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -294,10 +258,6 @@ func (k *contextKey) String() string { } var ( - // For Client - HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"} diff --git a/_examples/hello-webrpc-ts/server/hello_api.gen.go b/_examples/hello-webrpc-ts/server/hello_api.gen.go index 1180e41..af84e4e 100644 --- a/_examples/hello-webrpc-ts/server/hello_api.gen.go +++ b/_examples/hello-webrpc-ts/server/hello_api.gen.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strings" "time" @@ -111,44 +111,49 @@ func NewExampleServiceServer(svc ExampleService) WebRPCServer { } func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleService/Ping": - s.servePing(ctx, w, r) - return + handler = s.servePingJSON case "/rpc/ExampleService/GetUser": - s.serveGetUser(ctx, w, r) - return + handler = s.serveGetUserJSON case "/rpc/ExampleService/FindUsers": - s.serveFindUsers(ctx, w, r) - return + handler = s.serveFindUsersJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] } + contentType = strings.TrimSpace(strings.ToLower(contentType)) - switch strings.TrimSpace(strings.ToLower(header[:i])) { + switch contentType { case "application/json": - s.servePingJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -156,33 +161,22 @@ func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWri } func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.Ping(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + // Call service method implementation. + ret0, err := s.ExampleService.Ping(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -191,68 +185,37 @@ func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.Respons w.Write(respBody) } -func (s *exampleServiceServer) serveGetUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetUserJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") - reqContent := struct { - Arg0 uint64 `json:"userID"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 uint64 `json:"userID"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - var ret0 *User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.GetUser(ctx, reqContent.Arg0) - }() - respContent := struct { - Ret0 *User `json:"user"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") + // Call service method implementation. + ret0, err := s.ExampleService.GetUser(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *User `json:"user"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -261,70 +224,38 @@ func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.Resp w.Write(respBody) } -func (s *exampleServiceServer) serveFindUsers(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveFindUsersJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) +func (s *exampleServiceServer) serveFindUsersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + reqBody, err := io.ReadAll(r.Body) + if err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) + return } -} + defer r.Body.Close() -func (s *exampleServiceServer) serveFindUsersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "FindUsers") - reqContent := struct { + reqPayload := struct { Arg0 string `json:"q"` }{} - - reqBody, err := ioutil.ReadAll(r.Body) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) + ctx = context.WithValue(ctx, MethodNameCtxKey, "FindUsers") + + // Call service method implementation. + ret0, ret1, err := s.ExampleService.FindUsers(ctx, reqPayload.Arg0) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) RespondWithError(w, err) return } - // Call service method - var ret0 *Page - var ret1 []*User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, ret1, err = s.ExampleService.FindUsers(ctx, reqContent.Arg0) - }() - respContent := struct { + respPayload := struct { Ret0 *Page `json:"page"` Ret1 []*User `json:"users"` }{ret0, ret1} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -359,10 +290,6 @@ func (k *contextKey) String() string { } var ( - // For Client - HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"} diff --git a/_examples/hello-webrpc/server/hello_api.gen.go b/_examples/hello-webrpc/server/hello_api.gen.go index 39fe2d3..9751512 100644 --- a/_examples/hello-webrpc/server/hello_api.gen.go +++ b/_examples/hello-webrpc/server/hello_api.gen.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strings" "time" @@ -105,41 +105,47 @@ func NewExampleServiceServer(svc ExampleService) WebRPCServer { } func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleService/Ping": - s.servePing(ctx, w, r) - return + handler = s.servePingJSON case "/rpc/ExampleService/GetUser": - s.serveGetUser(ctx, w, r) - return + handler = s.serveGetUserJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return + } + + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] } + contentType = strings.TrimSpace(strings.ToLower(contentType)) - switch strings.TrimSpace(strings.ToLower(header[:i])) { + switch contentType { case "application/json": - s.servePingJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -147,33 +153,22 @@ func (s *exampleServiceServer) servePing(ctx context.Context, w http.ResponseWri } func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") - // Call service method - var ret0 bool - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.Ping(ctx) - }() - respContent := struct { - Ret0 bool `json:"status"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "Ping") + // Call service method implementation. + ret0, err := s.ExampleService.Ping(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 bool `json:"status"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -182,68 +177,37 @@ func (s *exampleServiceServer) servePingJSON(ctx context.Context, w http.Respons w.Write(respBody) } -func (s *exampleServiceServer) serveGetUser(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetUserJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *exampleServiceServer) serveGetUserJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") - reqContent := struct { - Arg0 uint64 `json:"userID"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 uint64 `json:"userID"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - var ret0 *User - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.ExampleService.GetUser(ctx, reqContent.Arg0) - }() - respContent := struct { - Ret0 *User `json:"user"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetUser") + // Call service method implementation. + ret0, err := s.ExampleService.GetUser(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *User `json:"user"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -278,10 +242,6 @@ func (k *contextKey) String() string { } var ( - // For Client - HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"} diff --git a/tests/client/client.gen.go b/tests/client/client.gen.go index a25c016..efe301e 100644 --- a/tests/client/client.gen.go +++ b/tests/client/client.gen.go @@ -12,7 +12,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "net/url" ) @@ -296,7 +295,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if resp.StatusCode != 200 { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read server error response body: %w", err)) } @@ -312,7 +311,7 @@ func doJSONRequest(ctx context.Context, client HTTPClient, url string, in, out i } if out != nil { - respBody, err := ioutil.ReadAll(resp.Body) + respBody, err := io.ReadAll(resp.Body) if err != nil { return ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to read response body: %w", err)) } @@ -365,12 +364,8 @@ func (k *contextKey) String() string { } var ( - // For Client HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - // For Server - HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} - HTTPRequestCtxKey = &contextKey{"HTTPRequest"} ServiceNameCtxKey = &contextKey{"ServiceName"} diff --git a/tests/server/server.gen.go b/tests/server/server.gen.go index 9ab1f52..d52a7c4 100644 --- a/tests/server/server.gen.go +++ b/tests/server/server.gen.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strings" ) @@ -133,62 +133,61 @@ func NewTestApiServer(svc TestApi) WebRPCServer { } func (s *testApiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + defer func() { + // In case of a panic, serve a HTTP 500 error and then panic. + if rr := recover(); rr != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) + panic(rr) + } + }() + ctx := r.Context() ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "TestApi") - if r.Method != "POST" { - err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) - RespondWithError(w, err) - return - } - + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/TestApi/GetEmpty": - s.serveGetEmpty(ctx, w, r) - return + handler = s.serveGetEmptyJSON case "/rpc/TestApi/GetError": - s.serveGetError(ctx, w, r) - return + handler = s.serveGetErrorJSON case "/rpc/TestApi/GetOne": - s.serveGetOne(ctx, w, r) - return + handler = s.serveGetOneJSON case "/rpc/TestApi/SendOne": - s.serveSendOne(ctx, w, r) - return + handler = s.serveSendOneJSON case "/rpc/TestApi/GetMulti": - s.serveGetMulti(ctx, w, r) - return + handler = s.serveGetMultiJSON case "/rpc/TestApi/SendMulti": - s.serveSendMulti(ctx, w, r) - return + handler = s.serveSendMultiJSON case "/rpc/TestApi/GetComplex": - s.serveGetComplex(ctx, w, r) - return + handler = s.serveGetComplexJSON case "/rpc/TestApi/SendComplex": - s.serveSendComplex(ctx, w, r) - return + handler = s.serveSendComplexJSON case "/rpc/TestApi/GetSchemaError": - s.serveGetSchemaError(ctx, w, r) - return + handler = s.serveGetSchemaErrorJSON default: err := ErrorWithCause(ErrWebrpcBadRoute, fmt.Errorf("no handler for path %q", r.URL.Path)) RespondWithError(w, err) return } -} -func (s *testApiServer) serveGetEmpty(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) + if r.Method != "POST" { + w.Header().Add("Allow", "POST") // RFC 9110. + err := ErrorWithCause(ErrWebrpcBadMethod, fmt.Errorf("unsupported method %q (only POST is allowed)", r.Method)) + RespondWithError(w, err) + return } - switch strings.TrimSpace(strings.ToLower(header[:i])) { + contentType := r.Header.Get("Content-Type") + if i := strings.Index(contentType, ";"); i >= 0 { + contentType = contentType[:i] + } + contentType = strings.TrimSpace(strings.ToLower(contentType)) + + switch contentType { case "application/json": - s.serveGetEmptyJSON(ctx, w, r) + handler(ctx, w, r) default: err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) RespondWithError(w, err) @@ -196,21 +195,11 @@ func (s *testApiServer) serveGetEmpty(ctx context.Context, w http.ResponseWriter } func (s *testApiServer) serveGetEmptyJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetEmpty") - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.GetEmpty(ctx) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetEmpty") + // Call service method implementation. + err := s.TestApi.GetEmpty(ctx) if err != nil { RespondWithError(w, err) return @@ -221,38 +210,12 @@ func (s *testApiServer) serveGetEmptyJSON(ctx context.Context, w http.ResponseWr w.Write([]byte("{}")) } -func (s *testApiServer) serveGetError(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetErrorJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveGetErrorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetError") - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.GetError(ctx) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetError") + // Call service method implementation. + err := s.TestApi.GetError(ctx) if err != nil { RespondWithError(w, err) return @@ -263,50 +226,23 @@ func (s *testApiServer) serveGetErrorJSON(ctx context.Context, w http.ResponseWr w.Write([]byte("{}")) } -func (s *testApiServer) serveGetOne(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetOneJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveGetOneJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetOne") - // Call service method - var ret0 *Simple - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.TestApi.GetOne(ctx) - }() - respContent := struct { - Ret0 *Simple `json:"one"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetOne") + // Call service method implementation. + ret0, err := s.TestApi.GetOne(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *Simple `json:"one"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -315,56 +251,26 @@ func (s *testApiServer) serveGetOneJSON(ctx context.Context, w http.ResponseWrit w.Write(respBody) } -func (s *testApiServer) serveSendOne(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveSendOneJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveSendOneJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "SendOne") - reqContent := struct { - Arg0 *Simple `json:"one"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 *Simple `json:"one"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.SendOne(ctx, reqContent.Arg0) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "SendOne") + // Call service method implementation. + err = s.TestApi.SendOne(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return @@ -375,54 +281,25 @@ func (s *testApiServer) serveSendOneJSON(ctx context.Context, w http.ResponseWri w.Write([]byte("{}")) } -func (s *testApiServer) serveGetMulti(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } +func (s *testApiServer) serveGetMultiJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetMultiJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMulti") + + // Call service method implementation. + ret0, ret1, ret2, err := s.TestApi.GetMulti(ctx) + if err != nil { RespondWithError(w, err) + return } -} - -func (s *testApiServer) serveGetMultiJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetMulti") - // Call service method - var ret0 *Simple - var ret1 *Simple - var ret2 *Simple - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, ret1, ret2, err = s.TestApi.GetMulti(ctx) - }() - respContent := struct { + respPayload := struct { Ret0 *Simple `json:"one"` Ret1 *Simple `json:"two"` Ret2 *Simple `json:"three"` }{ret0, ret1, ret2} - - if err != nil { - RespondWithError(w, err) - return - } - respBody, err := json.Marshal(respContent) + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -431,58 +308,28 @@ func (s *testApiServer) serveGetMultiJSON(ctx context.Context, w http.ResponseWr w.Write(respBody) } -func (s *testApiServer) serveSendMulti(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveSendMultiJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveSendMultiJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "SendMulti") - reqContent := struct { - Arg0 *Simple `json:"one"` - Arg1 *Simple `json:"two"` - Arg2 *Simple `json:"three"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 *Simple `json:"one"` + Arg1 *Simple `json:"two"` + Arg2 *Simple `json:"three"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.SendMulti(ctx, reqContent.Arg0, reqContent.Arg1, reqContent.Arg2) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "SendMulti") + // Call service method implementation. + err = s.TestApi.SendMulti(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) if err != nil { RespondWithError(w, err) return @@ -493,50 +340,23 @@ func (s *testApiServer) serveSendMultiJSON(ctx context.Context, w http.ResponseW w.Write([]byte("{}")) } -func (s *testApiServer) serveGetComplex(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetComplexJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveGetComplexJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetComplex") - // Call service method - var ret0 *Complex - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - ret0, err = s.TestApi.GetComplex(ctx) - }() - respContent := struct { - Ret0 *Complex `json:"complex"` - }{ret0} + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetComplex") + // Call service method implementation. + ret0, err := s.TestApi.GetComplex(ctx) if err != nil { RespondWithError(w, err) return } - respBody, err := json.Marshal(respContent) + + respPayload := struct { + Ret0 *Complex `json:"complex"` + }{ret0} + respBody, err := json.Marshal(respPayload) if err != nil { - err = ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadResponse, fmt.Errorf("failed to marshal json response: %w", err))) return } @@ -545,56 +365,26 @@ func (s *testApiServer) serveGetComplexJSON(ctx context.Context, w http.Response w.Write(respBody) } -func (s *testApiServer) serveSendComplex(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveSendComplexJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveSendComplexJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "SendComplex") - reqContent := struct { - Arg0 *Complex `json:"complex"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 *Complex `json:"complex"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.SendComplex(ctx, reqContent.Arg0) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "SendComplex") + // Call service method implementation. + err = s.TestApi.SendComplex(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return @@ -605,56 +395,26 @@ func (s *testApiServer) serveSendComplexJSON(ctx context.Context, w http.Respons w.Write([]byte("{}")) } -func (s *testApiServer) serveGetSchemaError(ctx context.Context, w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Content-Type") - i := strings.Index(header, ";") - if i == -1 { - i = len(header) - } - - switch strings.TrimSpace(strings.ToLower(header[:i])) { - case "application/json": - s.serveGetSchemaErrorJSON(ctx, w, r) - default: - err := ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("unexpected Content-Type: %q", r.Header.Get("Content-Type"))) - RespondWithError(w, err) - } -} - func (s *testApiServer) serveGetSchemaErrorJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { - var err error - ctx = context.WithValue(ctx, MethodNameCtxKey, "GetSchemaError") - reqContent := struct { - Arg0 int `json:"code"` - }{} - - reqBody, err := ioutil.ReadAll(r.Body) + reqBody, err := io.ReadAll(r.Body) if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err)) - RespondWithError(w, err) + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to read request data: %w", err))) return } defer r.Body.Close() - err = json.Unmarshal(reqBody, &reqContent) - if err != nil { - err = ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err)) - RespondWithError(w, err) + reqPayload := struct { + Arg0 int `json:"code"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + RespondWithError(w, ErrorWithCause(ErrWebrpcBadRequest, fmt.Errorf("failed to unmarshal request data: %w", err))) return } - // Call service method - func() { - defer func() { - // In case of a panic, serve a 500 error and then panic. - if rr := recover(); rr != nil { - RespondWithError(w, ErrorWithCause(ErrWebrpcServerPanic, fmt.Errorf("%v", rr))) - panic(rr) - } - }() - err = s.TestApi.GetSchemaError(ctx, reqContent.Arg0) - }() + ctx = context.WithValue(ctx, MethodNameCtxKey, "GetSchemaError") + // Call service method implementation. + err = s.TestApi.GetSchemaError(ctx, reqPayload.Arg0) if err != nil { RespondWithError(w, err) return @@ -691,10 +451,6 @@ func (k *contextKey) String() string { } var ( - // For Client - HTTPClientRequestHeadersCtxKey = &contextKey{"HTTPClientRequestHeaders"} - - // For Server HTTPResponseWriterCtxKey = &contextKey{"HTTPResponseWriter"} HTTPRequestCtxKey = &contextKey{"HTTPRequest"}