From 430da6408cba4716c2bf9fa7ae1fbad17b4d05a2 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Wed, 25 Sep 2024 21:47:37 +0200 Subject: [PATCH 01/18] call onDeprecate hook when method is deprecated --- server.go.tmpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server.go.tmpl b/server.go.tmpl index 67dc7f3..1213828 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -20,6 +20,7 @@ type WebRPCServer interface { type {{$serviceName}} struct { {{$typePrefix}}{{$service.Name}} OnError func(r *http.Request, rpcErr *WebRPCError) + OnDeprecate func(endpoint string, newEndpoint string) } func New{{firstLetterToUpper $service.Name}}Server(svc {{$typePrefix}}{{.Name}}) *{{$serviceName}} { @@ -46,6 +47,10 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { {{- range $_, $method := $service.Methods}} case "/rpc/{{$name}}/{{$method.Name}}": + {{- $deprecated := $method.Annotations.Deprecated -}} + {{- if $deprecated -}} + s.OnDeprecate("{{ $method.Name }}", "{{ index $deprecated.Args 0 }}") + {{- end}} handler = s.serve{{$method.Name | firstLetterToUpper}}JSON{{if $method.StreamOutput}}Stream{{end}} {{- end}} default: From 59679f1868dca282a66a8a42a3b4ac4becc5e495 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Thu, 26 Sep 2024 10:32:34 +0200 Subject: [PATCH 02/18] add request to deprecate hook --- .github/workflows/ci.yml | 2 +- helpers.go.tmpl | 7 +++++++ server.go.tmpl | 23 ++++++++++++++++++----- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0506e9..9d2f7dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: with: go-version: "1.20" - name: Install webrpc-gen (development) - run: git clone --single-branch https://github.com/webrpc/webrpc.git --branch master && cd webrpc && make install + run: git clone --single-branch https://github.com/webrpc/webrpc.git --branch deprecate_methods_v2 && cd webrpc && make install - name: Regenerate examples run: cd _examples && make generate diff --git a/helpers.go.tmpl b/helpers.go.tmpl index c743309..e0a1ba1 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -26,6 +26,8 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} + + AnnotationsCtxKey = &contextKey{"Annotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -43,6 +45,11 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } +func AnnotationsFromContext(ctx context.Context) map[string]string { + annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) + return annotations +} + {{- if $opts.server}} func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) diff --git a/server.go.tmpl b/server.go.tmpl index 1213828..f928446 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -17,10 +17,22 @@ type WebRPCServer interface { {{- $name := $service.Name -}} {{ $serviceName := (printf "%sServer" (firstLetterToLower $service.Name)) }} +var ( + annotations = map[string]map[string]string{ + {{- range $_, $method := $service.Methods}} + "/rpc/{{$name}}/{{$method.Name}}": { + {{- range $_, $annotation := $method.Annotations -}} + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + {{- end -}} + }, + {{- end -}} + } +) + type {{$serviceName}} struct { {{$typePrefix}}{{$service.Name}} OnError func(r *http.Request, rpcErr *WebRPCError) - OnDeprecate func(endpoint string, newEndpoint string) + OnRequest func(w http.ResponseWriter, r *http.Request) } func New{{firstLetterToUpper $service.Name}}Server(svc {{$typePrefix}}{{.Name}}) *{{$serviceName}} { @@ -42,15 +54,16 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "{{.Name}}") + ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + + if s.OnRequest != nil { + s.OnRequest(w, r) + } var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { {{- range $_, $method := $service.Methods}} case "/rpc/{{$name}}/{{$method.Name}}": - {{- $deprecated := $method.Annotations.Deprecated -}} - {{- if $deprecated -}} - s.OnDeprecate("{{ $method.Name }}", "{{ index $deprecated.Args 0 }}") - {{- end}} handler = s.serve{{$method.Name | firstLetterToUpper}}JSON{{if $method.StreamOutput}}Stream{{end}} {{- end}} default: From 0fa46766591fa9b8b12db996c582170b80896e6e Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Thu, 26 Sep 2024 17:20:47 +0200 Subject: [PATCH 03/18] regenerate examples with latest webrpc --- _examples/golang-basics/example.gen.go | 31 ++++++++++++++++++++++---- _examples/golang-imports/api.gen.go | 26 ++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index a59409b..ebabb62 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ -// example v0.0.1 3a3a4087149f1118f0b9494fa254afab46564a1b +// example v0.0.1 9d2e85c0083323599454454bc06526ab08edd24e // -- -// Code generated by webrpc-gen@v0.19.3 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-8-g87b50a2 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -33,7 +33,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "3a3a4087149f1118f0b9494fa254afab46564a1b" + return "9d2e85c0083323599454454bc06526ab08edd24e" } // @@ -211,9 +211,20 @@ type WebRPCServer interface { http.Handler } +var ( + annotations = map[string]map[string]string{ + "/rpc/ExampleService/Ping": {}, + "/rpc/ExampleService/Status": {}, + "/rpc/ExampleService/Version": {}, + "/rpc/ExampleService/GetUser": {}, + "/rpc/ExampleService/FindUser": {}, + "/rpc/ExampleService/LogEvent": {}} +) + type exampleServiceServer struct { ExampleService - OnError func(r *http.Request, rpcErr *WebRPCError) + OnError func(r *http.Request, rpcErr *WebRPCError) + OnRequest func(w http.ResponseWriter, r *http.Request) } func NewExampleServiceServer(svc ExampleService) *exampleServiceServer { @@ -235,6 +246,11 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") + ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + + if s.OnRequest != nil { + s.OnRequest(w, r) + } var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -766,6 +782,8 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} + + AnnotationsCtxKey = &contextKey{"Annotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -782,6 +800,11 @@ func RequestFromContext(ctx context.Context) *http.Request { r, _ := ctx.Value(HTTPRequestCtxKey).(*http.Request) return r } + +func AnnotationsFromContext(ctx context.Context) map[string]string { + annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) + return annotations +} func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) return w diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index e454f74..f717b10 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ -// example-api-service v1.0.0 eb9a5d4082a36a8cb84eaa4b3e1091fc4f1f6f3d +// example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-8-g87b50a2 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -30,7 +30,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "eb9a5d4082a36a8cb84eaa4b3e1091fc4f1f6f3d" + return "cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af" } // @@ -126,9 +126,17 @@ type WebRPCServer interface { http.Handler } +var ( + annotations = map[string]map[string]string{ + "/rpc/ExampleAPI/Ping": {}, + "/rpc/ExampleAPI/Status": {}, + "/rpc/ExampleAPI/GetUsers": {},} +) + type exampleAPIServer struct { ExampleAPI OnError func(r *http.Request, rpcErr *WebRPCError) + OnRequest func(w http.ResponseWriter, r *http.Request) } func NewExampleAPIServer(svc ExampleAPI) *exampleAPIServer { @@ -150,6 +158,11 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") + ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + + if s.OnRequest != nil { + s.OnRequest(w, r) + } var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -507,6 +520,8 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} + + AnnotationsCtxKey = &contextKey{"Annotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -523,6 +538,11 @@ func RequestFromContext(ctx context.Context) *http.Request { r, _ := ctx.Value(HTTPRequestCtxKey).(*http.Request) return r } + +func AnnotationsFromContext(ctx context.Context) map[string]string { + annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) + return annotations +} func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) return w From 2825c44b2f53b887a29909afad34193b074cb77b Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 11:25:59 +0200 Subject: [PATCH 04/18] return error from OnRequest hook --- server.go.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go.tmpl b/server.go.tmpl index f928446..00e002e 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -32,7 +32,7 @@ var ( type {{$serviceName}} struct { {{$typePrefix}}{{$service.Name}} OnError func(r *http.Request, rpcErr *WebRPCError) - OnRequest func(w http.ResponseWriter, r *http.Request) + OnRequest func(w http.ResponseWriter, r *http.Request) error } func New{{firstLetterToUpper $service.Name}}Server(svc {{$typePrefix}}{{.Name}}) *{{$serviceName}} { From 00901d6ebbc49873b62f5038515099378f9535b4 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 11:28:47 +0200 Subject: [PATCH 05/18] rename to MethodAnnotationsFromContext --- helpers.go.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers.go.tmpl b/helpers.go.tmpl index e0a1ba1..cd41541 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -45,7 +45,7 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func AnnotationsFromContext(ctx context.Context) map[string]string { +func MethodAnnotationsFromContext(ctx context.Context) map[string]string { annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) return annotations } From a210d4172943d310657079fda5fdf0fd745c14d1 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 11:58:03 +0200 Subject: [PATCH 06/18] move annotations render to common (client, server) tmpl --- main.go.tmpl | 16 ++++++++++++++++ server.go.tmpl | 12 ------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/main.go.tmpl b/main.go.tmpl index e298dd4..57ff005 100644 --- a/main.go.tmpl +++ b/main.go.tmpl @@ -102,6 +102,22 @@ func WebRPCSchemaHash() string { {{ template "types" dict "Services" .Services "Types" .Types "TypeMap" $typeMap "TypePrefix" $typePrefix "Opts" $opts }} {{ end -}} +{{- if .Services -}} +{{- range $_, $service := .Services -}} +var ( + annotations = map[string]map[string]string{ + {{- range $_, $method := $service.Methods }} + "/rpc/{{$service.Name}}/{{$method.Name}}": { + {{- range $_, $annotation := $method.Annotations -}} + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + {{- end -}} + }, + {{- end }} + } +) +{{ end }} +{{- end}} + {{- if $opts.server }} {{ template "server" dict "Services" .Services "TypeMap" $typeMap "TypePrefix" $typePrefix "Opts" $opts }} {{ end -}} diff --git a/server.go.tmpl b/server.go.tmpl index 00e002e..dad9d89 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -17,18 +17,6 @@ type WebRPCServer interface { {{- $name := $service.Name -}} {{ $serviceName := (printf "%sServer" (firstLetterToLower $service.Name)) }} -var ( - annotations = map[string]map[string]string{ - {{- range $_, $method := $service.Methods}} - "/rpc/{{$name}}/{{$method.Name}}": { - {{- range $_, $annotation := $method.Annotations -}} - "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", - {{- end -}} - }, - {{- end -}} - } -) - type {{$serviceName}} struct { {{$typePrefix}}{{$service.Name}} OnError func(r *http.Request, rpcErr *WebRPCError) From 2bf28b8eae5340914f958d67c2afa2c818ffd0f6 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 12:06:46 +0200 Subject: [PATCH 07/18] move annotations above WebRPC services --- main.go.tmpl | 16 ---------------- types.go.tmpl | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/main.go.tmpl b/main.go.tmpl index 57ff005..e298dd4 100644 --- a/main.go.tmpl +++ b/main.go.tmpl @@ -102,22 +102,6 @@ func WebRPCSchemaHash() string { {{ template "types" dict "Services" .Services "Types" .Types "TypeMap" $typeMap "TypePrefix" $typePrefix "Opts" $opts }} {{ end -}} -{{- if .Services -}} -{{- range $_, $service := .Services -}} -var ( - annotations = map[string]map[string]string{ - {{- range $_, $method := $service.Methods }} - "/rpc/{{$service.Name}}/{{$method.Name}}": { - {{- range $_, $annotation := $method.Annotations -}} - "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", - {{- end -}} - }, - {{- end }} - } -) -{{ end }} -{{- end}} - {{- if $opts.server }} {{ template "server" dict "Services" .Services "TypeMap" $typeMap "TypePrefix" $typePrefix "Opts" $opts }} {{ end -}} diff --git a/types.go.tmpl b/types.go.tmpl index 9b88d38..ee304a8 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -29,6 +29,21 @@ {{- end }} +{{- range $_, $service := $services -}} +var ( + annotations = map[string]map[string]string{ + {{- range $_, $method := $service.Methods }} + "/rpc/{{$service.Name}}/{{$method.Name}}": { + {{- range $_, $annotation := $method.Annotations -}} + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + {{- end -}} + }, + {{- end }} + } +) +{{ end }} + + var WebRPCServices = map[string][]string{ {{- range $_, $service := $services}} "{{$service.Name}}": { From f8297fa15fe5d8aed1c0156f49409fdcc66d4278 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 12:07:55 +0200 Subject: [PATCH 08/18] rename to methodAnotations --- types.go.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types.go.tmpl b/types.go.tmpl index ee304a8..5e0af53 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -31,7 +31,7 @@ {{- range $_, $service := $services -}} var ( - annotations = map[string]map[string]string{ + methodAnnotations = map[string]map[string]string{ {{- range $_, $method := $service.Methods }} "/rpc/{{$service.Name}}/{{$method.Name}}": { {{- range $_, $annotation := $method.Annotations -}} From c5c552825453e6aaf68fbf62094494cc1d222d5b Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Fri, 27 Sep 2024 12:11:56 +0200 Subject: [PATCH 09/18] rename to MethodAnnotationsFromCtx --- _examples/golang-basics/example.gen.go | 37 +++++++++++++------------- _examples/golang-basics/example.ridl | 1 + _examples/golang-imports/api.gen.go | 29 ++++++++++---------- helpers.go.tmpl | 4 +-- server.go.tmpl | 2 +- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index ebabb62..af47cad 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ -// example v0.0.1 9d2e85c0083323599454454bc06526ab08edd24e +// example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-8-g87b50a2 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-11-g71ce490 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -33,7 +33,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "9d2e85c0083323599454454bc06526ab08edd24e" + return "05b7a5c86b98738f4fe6ce9bb1fccd4af064847a" } // @@ -160,6 +160,17 @@ type ComplexType struct { User *User `json:"user"` } +var ( + methodAnnotations = map[string]map[string]string{ + "/rpc/ExampleService/Ping": {}, + "/rpc/ExampleService/Status": {"internal": ""}, + "/rpc/ExampleService/Version": {}, + "/rpc/ExampleService/GetUser": {}, + "/rpc/ExampleService/FindUser": {}, + "/rpc/ExampleService/LogEvent": {}, + } +) + var WebRPCServices = map[string][]string{ "ExampleService": { "Ping", @@ -211,20 +222,10 @@ type WebRPCServer interface { http.Handler } -var ( - annotations = map[string]map[string]string{ - "/rpc/ExampleService/Ping": {}, - "/rpc/ExampleService/Status": {}, - "/rpc/ExampleService/Version": {}, - "/rpc/ExampleService/GetUser": {}, - "/rpc/ExampleService/FindUser": {}, - "/rpc/ExampleService/LogEvent": {}} -) - type exampleServiceServer struct { ExampleService OnError func(r *http.Request, rpcErr *WebRPCError) - OnRequest func(w http.ResponseWriter, r *http.Request) + OnRequest func(w http.ResponseWriter, r *http.Request) error } func NewExampleServiceServer(svc ExampleService) *exampleServiceServer { @@ -246,7 +247,7 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) if s.OnRequest != nil { s.OnRequest(w, r) @@ -783,7 +784,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - AnnotationsCtxKey = &contextKey{"Annotations"} + MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -801,8 +802,8 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func AnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) +func MethodAnnotationsFromContext(ctx context.Context) map[string]string { + annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) return annotations } func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { diff --git a/_examples/golang-basics/example.ridl b/_examples/golang-basics/example.ridl index 9b9f739..d60169f 100644 --- a/_examples/golang-basics/example.ridl +++ b/_examples/golang-basics/example.ridl @@ -92,6 +92,7 @@ service ExampleService # Status endpoint # # gives you current status of running application + @internal - Status() => (status: bool) - Version() => (version: Version) - GetUser(header: map, userID: uint64) => (user: User) diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index f717b10..213d8fe 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-8-g87b50a2 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-11-g71ce490 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -82,7 +82,15 @@ func (x *Location) Is(values ...Location) bool { } } return false -} +}var ( + methodAnnotations = map[string]map[string]string{ + "/rpc/ExampleAPI/Ping": {}, + "/rpc/ExampleAPI/Status": {}, + "/rpc/ExampleAPI/GetUsers": {}, + } +) + + var WebRPCServices = map[string][]string{ "ExampleAPI": { @@ -126,17 +134,10 @@ type WebRPCServer interface { http.Handler } -var ( - annotations = map[string]map[string]string{ - "/rpc/ExampleAPI/Ping": {}, - "/rpc/ExampleAPI/Status": {}, - "/rpc/ExampleAPI/GetUsers": {},} -) - type exampleAPIServer struct { ExampleAPI OnError func(r *http.Request, rpcErr *WebRPCError) - OnRequest func(w http.ResponseWriter, r *http.Request) + OnRequest func(w http.ResponseWriter, r *http.Request) error } func NewExampleAPIServer(svc ExampleAPI) *exampleAPIServer { @@ -158,7 +159,7 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") - ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) if s.OnRequest != nil { s.OnRequest(w, r) @@ -521,7 +522,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - AnnotationsCtxKey = &contextKey{"Annotations"} + MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -539,8 +540,8 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func AnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) +func MethodAnnotationsFromContext(ctx context.Context) map[string]string { + annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) return annotations } func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { diff --git a/helpers.go.tmpl b/helpers.go.tmpl index cd41541..32036d8 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -27,7 +27,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - AnnotationsCtxKey = &contextKey{"Annotations"} + MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -46,7 +46,7 @@ func RequestFromContext(ctx context.Context) *http.Request { } func MethodAnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(AnnotationsCtxKey).(map[string]string) + annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) return annotations } diff --git a/server.go.tmpl b/server.go.tmpl index dad9d89..87039a1 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -42,7 +42,7 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "{{.Name}}") - ctx = context.WithValue(ctx, AnnotationsCtxKey, annotations[r.URL.Path]) + ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) if s.OnRequest != nil { s.OnRequest(w, r) From 1afdb0d6e6b0926ea303c73096a336158e061929 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 12:30:05 +0200 Subject: [PATCH 10/18] call OnRequest before handler is called and handle err --- _examples/golang-basics/example.gen.go | 41 +++++++++++++++++------ _examples/golang-imports/api.gen.go | 46 ++++++++++++++++++++------ helpers.go.tmpl | 23 ++++++++++--- server.go.tmpl | 17 +++++++--- types.go.tmpl | 2 +- 5 files changed, 97 insertions(+), 32 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index af47cad..2efa6ea 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ // example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-11-g71ce490 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-14-g44bb43f with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -247,11 +247,7 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) - - if s.OnRequest != nil { - s.OnRequest(w, r) - } + ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -288,6 +284,17 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) switch contentType { case "application/json": + if s.OnRequest != nil { + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + } + handler(ctx, w, r) default: err := ErrWebrpcBadRequest.WithCause(fmt.Errorf("unsupported Content-Type %q (only application/json is allowed)", r.Header.Get("Content-Type"))) @@ -766,6 +773,12 @@ func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { // Helpers // +type MethodCtx struct { + Name string + Service string + Annotations map[string]string +} + type contextKey struct { name string } @@ -784,7 +797,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} + methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -802,10 +815,18 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodAnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) - return annotations +func MethodFromContext(ctx context.Context) MethodCtx { + name, _ := ctx.Value(MethodNameCtxKey).(string) + service, _ := ctx.Value(ServiceNameCtxKey).(string) + annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + + return MethodCtx{ + Name: name, + Service: service, + Annotations: annotations, + } } + func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) return w diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index 213d8fe..c11695d 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-11-g71ce490 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-14-g44bb43f with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -82,7 +82,9 @@ func (x *Location) Is(values ...Location) bool { } } return false -}var ( +} + +var ( methodAnnotations = map[string]map[string]string{ "/rpc/ExampleAPI/Ping": {}, "/rpc/ExampleAPI/Status": {}, @@ -159,11 +161,7 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") - ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) - - if s.OnRequest != nil { - s.OnRequest(w, r) - } + ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -194,6 +192,17 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": + if s.OnRequest != nil { + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + } + handler(ctx, w, r) default: err := ErrWebrpcBadRequest.WithCause(fmt.Errorf("unsupported Content-Type %q (only application/json is allowed)", r.Header.Get("Content-Type"))) @@ -504,6 +513,12 @@ func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { // Helpers // +type MethodCtx struct { + Name string + Service string + Annotations map[string]string +} + type contextKey struct { name string } @@ -522,7 +537,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} + methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -540,10 +555,19 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodAnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) - return annotations +func MethodFromContext(ctx context.Context) MethodCtx { + name, _ := ctx.Value(MethodNameCtxKey).(string) + service, _ := ctx.Value(ServiceNameCtxKey).(string) + annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + + return MethodCtx{ + Name: name, + Service: service, + Annotations: annotations, + } } + + func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) return w diff --git a/helpers.go.tmpl b/helpers.go.tmpl index 32036d8..3a7f2ad 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -5,6 +5,12 @@ // Helpers // +type MethodCtx struct { + Name string + Service string + Annotations map[string]string +} + type contextKey struct { name string } @@ -27,7 +33,7 @@ var ( MethodNameCtxKey = &contextKey{"MethodName"} - MethodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} + methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -45,12 +51,19 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodAnnotationsFromContext(ctx context.Context) map[string]string { - annotations, _ := ctx.Value(MethodAnnotationsCtxKey).(map[string]string) - return annotations +func MethodFromContext(ctx context.Context) MethodCtx { + name, _ := ctx.Value(MethodNameCtxKey).(string) + service, _ := ctx.Value(ServiceNameCtxKey).(string) + annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + + return MethodCtx{ + Name: name, + Service: service, + Annotations: annotations, + } } -{{- if $opts.server}} +{{ if $opts.server}} func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { w, _ := ctx.Value(HTTPResponseWriterCtxKey).(http.ResponseWriter) return w diff --git a/server.go.tmpl b/server.go.tmpl index 87039a1..fba3aa2 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -42,11 +42,7 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "{{.Name}}") - ctx = context.WithValue(ctx, MethodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) - - if s.OnRequest != nil { - s.OnRequest(w, r) - } + ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -75,6 +71,17 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": + if s.OnRequest != nil { + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + } + handler(ctx, w, r) default: err := ErrWebrpcBadRequest.WithCause(fmt.Errorf("unsupported Content-Type %q (only application/json is allowed)", r.Header.Get("Content-Type"))) diff --git a/types.go.tmpl b/types.go.tmpl index 5e0af53..1a1b2dd 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -29,7 +29,7 @@ {{- end }} -{{- range $_, $service := $services -}} +{{ range $_, $service := $services -}} var ( methodAnnotations = map[string]map[string]string{ {{- range $_, $method := $service.Methods }} From eb898b703ed8cb25510993c0dcfca0553099bbf2 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 12:58:59 +0200 Subject: [PATCH 11/18] use tabs --- .github/workflows/ci.yml | 2 +- _examples/golang-imports/api.gen.go | 16 ++++++++-------- server.go.tmpl | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d2f7dc..d0506e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: with: go-version: "1.20" - name: Install webrpc-gen (development) - run: git clone --single-branch https://github.com/webrpc/webrpc.git --branch deprecate_methods_v2 && cd webrpc && make install + run: git clone --single-branch https://github.com/webrpc/webrpc.git --branch master && cd webrpc && make install - name: Regenerate examples run: cd _examples && make generate diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index c11695d..bae798a 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -193,14 +193,14 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": if s.OnRequest != nil { - if err := s.OnRequest(w, r); err != nil { - rpcErr, ok := err.(WebRPCError) - if !ok { - rpcErr = ErrWebrpcEndpoint.WithCause(err) - } - s.sendErrorJSON(w, r, rpcErr) - return - } + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } } handler(ctx, w, r) diff --git a/server.go.tmpl b/server.go.tmpl index fba3aa2..5c0a77a 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -72,14 +72,14 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": if s.OnRequest != nil { - if err := s.OnRequest(w, r); err != nil { - rpcErr, ok := err.(WebRPCError) - if !ok { - rpcErr = ErrWebrpcEndpoint.WithCause(err) - } - s.sendErrorJSON(w, r, rpcErr) - return - } + if err := s.OnRequest(w, r); err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } } handler(ctx, w, r) From 2029ca92f1547fa6ac3dac74fe5b7e1c77ea1a19 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 14:31:31 +0200 Subject: [PATCH 12/18] generate annotations for multiple services in the same map --- _examples/golang-basics/example.gen.go | 2 +- _examples/golang-imports/api.gen.go | 10 ++++------ types.go.tmpl | 19 +++++++++---------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 2efa6ea..a8d745e 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ // example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-14-g44bb43f with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-14-g132051b with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index bae798a..3127573 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-14-g44bb43f with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-14-g132051b with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -86,14 +86,12 @@ func (x *Location) Is(values ...Location) bool { var ( methodAnnotations = map[string]map[string]string{ - "/rpc/ExampleAPI/Ping": {}, - "/rpc/ExampleAPI/Status": {}, - "/rpc/ExampleAPI/GetUsers": {}, + "/rpc/ExampleAPI/Ping": {}, + "/rpc/ExampleAPI/Status": {}, + "/rpc/ExampleAPI/GetUsers": {}, } ) - - var WebRPCServices = map[string][]string{ "ExampleAPI": { "Ping", diff --git a/types.go.tmpl b/types.go.tmpl index 1a1b2dd..6cd3b19 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -29,20 +29,19 @@ {{- end }} -{{ range $_, $service := $services -}} var ( methodAnnotations = map[string]map[string]string{ - {{- range $_, $method := $service.Methods }} - "/rpc/{{$service.Name}}/{{$method.Name}}": { - {{- range $_, $annotation := $method.Annotations -}} - "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", - {{- end -}} - }, - {{- end }} + {{- range $_, $service := $services -}} + {{- range $_, $method := $service.Methods }} + "/rpc/{{$service.Name}}/{{$method.Name}}": { + {{- range $_, $annotation := $method.Annotations -}} + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + {{- end -}} + }, + {{- end -}} + {{ end }} } ) -{{ end }} - var WebRPCServices = map[string][]string{ {{- range $_, $service := $services}} From 2269e08fb5f61b27a8e2442ef9f6655597a9a812 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 15:28:04 +0200 Subject: [PATCH 13/18] prevent nil panics --- _examples/golang-basics/example.gen.go | 5 ++++- _examples/golang-imports/api.gen.go | 9 ++++++--- helpers.go.tmpl | 11 +++++++---- server.go.tmpl | 4 ++-- types.go.tmpl | 2 +- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index a8d745e..6603744 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -818,7 +818,10 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodFromContext(ctx context.Context) MethodCtx { name, _ := ctx.Value(MethodNameCtxKey).(string) service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + if !ok { + annotations = map[string]string{} + } return MethodCtx{ Name: name, diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index 3127573..7222f61 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -190,7 +190,7 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": - if s.OnRequest != nil { + if s.OnRequest != nil { if err := s.OnRequest(w, r); err != nil { rpcErr, ok := err.(WebRPCError) if !ok { @@ -199,7 +199,7 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.sendErrorJSON(w, r, rpcErr) return } - } + } handler(ctx, w, r) default: @@ -556,7 +556,10 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodFromContext(ctx context.Context) MethodCtx { name, _ := ctx.Value(MethodNameCtxKey).(string) service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + if !ok { + annotations = map[string]string{} + } return MethodCtx{ Name: name, diff --git a/helpers.go.tmpl b/helpers.go.tmpl index 3a7f2ad..cbf995d 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -6,9 +6,9 @@ // type MethodCtx struct { - Name string - Service string - Annotations map[string]string + Name string + Service string + Annotations map[string]string } type contextKey struct { @@ -54,7 +54,10 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodFromContext(ctx context.Context) MethodCtx { name, _ := ctx.Value(MethodNameCtxKey).(string) service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, _ := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) + if !ok { + annotations = map[string]string{} + } return MethodCtx{ Name: name, diff --git a/server.go.tmpl b/server.go.tmpl index 5c0a77a..6589f00 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -71,7 +71,7 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch contentType { case "application/json": - if s.OnRequest != nil { + if s.OnRequest != nil { if err := s.OnRequest(w, r); err != nil { rpcErr, ok := err.(WebRPCError) if !ok { @@ -80,7 +80,7 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.sendErrorJSON(w, r, rpcErr) return } - } + } handler(ctx, w, r) default: diff --git a/types.go.tmpl b/types.go.tmpl index 6cd3b19..6ec5115 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -35,7 +35,7 @@ var ( {{- range $_, $method := $service.Methods }} "/rpc/{{$service.Name}}/{{$method.Name}}": { {{- range $_, $annotation := $method.Annotations -}} - "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", {{- end -}} }, {{- end -}} From b9066db889533fa2df79101c51e6fce18ab7def2 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 15:54:14 +0200 Subject: [PATCH 14/18] render map[string]MethodCtx in template --- _examples/golang-basics/example.gen.go | 40 ++++++++++++++++++++------ _examples/golang-imports/api.gen.go | 28 ++++++++++++------ types.go.tmpl | 12 +++++--- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 6603744..179b8d1 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ // example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-14-g132051b with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-15-g3735deb with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -161,13 +161,37 @@ type ComplexType struct { } var ( - methodAnnotations = map[string]map[string]string{ - "/rpc/ExampleService/Ping": {}, - "/rpc/ExampleService/Status": {"internal": ""}, - "/rpc/ExampleService/Version": {}, - "/rpc/ExampleService/GetUser": {}, - "/rpc/ExampleService/FindUser": {}, - "/rpc/ExampleService/LogEvent": {}, + methodAnnotations = map[string]MethodCtx{ + "/rpc/ExampleService/Ping": { + Name: "Ping", + Service: "ExampleService", + Annotations: map[string]string{}, + }, + "/rpc/ExampleService/Status": { + Name: "Status", + Service: "ExampleService", + Annotations: map[string]string{"internal": ""}, + }, + "/rpc/ExampleService/Version": { + Name: "Version", + Service: "ExampleService", + Annotations: map[string]string{}, + }, + "/rpc/ExampleService/GetUser": { + Name: "GetUser", + Service: "ExampleService", + Annotations: map[string]string{}, + }, + "/rpc/ExampleService/FindUser": { + Name: "FindUser", + Service: "ExampleService", + Annotations: map[string]string{}, + }, + "/rpc/ExampleService/LogEvent": { + Name: "LogEvent", + Service: "ExampleService", + Annotations: map[string]string{}, + }, } ) diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index 7222f61..b1952d3 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-14-g132051b with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-15-g3735deb with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -85,10 +85,22 @@ func (x *Location) Is(values ...Location) bool { } var ( - methodAnnotations = map[string]map[string]string{ - "/rpc/ExampleAPI/Ping": {}, - "/rpc/ExampleAPI/Status": {}, - "/rpc/ExampleAPI/GetUsers": {}, + methodAnnotations = map[string]MethodCtx{ + "/rpc/ExampleAPI/Ping": { + Name: "Ping", + Service: "ExampleAPI", + Annotations: map[string]string{}, + }, + "/rpc/ExampleAPI/Status": { + Name: "Status", + Service: "ExampleAPI", + Annotations: map[string]string{}, + }, + "/rpc/ExampleAPI/GetUsers": { + Name: "GetUsers", + Service: "ExampleAPI", + Annotations: map[string]string{}, + }, } ) @@ -512,9 +524,9 @@ func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { // type MethodCtx struct { - Name string - Service string - Annotations map[string]string + Name string + Service string + Annotations map[string]string } type contextKey struct { diff --git a/types.go.tmpl b/types.go.tmpl index 6ec5115..adb77d8 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -30,13 +30,17 @@ {{- end }} var ( - methodAnnotations = map[string]map[string]string{ + methodAnnotations = map[string]MethodCtx{ {{- range $_, $service := $services -}} {{- range $_, $method := $service.Methods }} "/rpc/{{$service.Name}}/{{$method.Name}}": { - {{- range $_, $annotation := $method.Annotations -}} - "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", - {{- end -}} + Name: "{{$method.Name}}", + Service: "{{$service.Name}}", + Annotations: map[string]string{ + {{- range $_, $annotation := $method.Annotations -}} + "{{$annotation.AnnotationType}}": "{{$annotation.Value}}", + {{- end -}} + }, }, {{- end -}} {{ end }} From 35a7e2801d913daa8465cecb0ce780ab8f3e0938 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Mon, 30 Sep 2024 16:25:13 +0200 Subject: [PATCH 15/18] get method ctx using request --- _examples/golang-basics/example.gen.go | 17 ++++------------- _examples/golang-imports/api.gen.go | 17 ++++------------- helpers.go.tmpl | 16 ++++------------ server.go.tmpl | 1 - 4 files changed, 12 insertions(+), 39 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 179b8d1..981db09 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -271,7 +271,6 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") - ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -820,8 +819,6 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} - - methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -839,19 +836,13 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodFromContext(ctx context.Context) MethodCtx { - name, _ := ctx.Value(MethodNameCtxKey).(string) - service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) +func GetMethodCtx(r *http.Request) (MethodCtx, bool) { + ctx, ok := methodAnnotations[r.URL.Path] if !ok { - annotations = map[string]string{} + return MethodCtx{}, false } - return MethodCtx{ - Name: name, - Service: service, - Annotations: annotations, - } + return ctx, true } func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index b1952d3..ea7cd4c 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -171,7 +171,6 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") - ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { @@ -546,8 +545,6 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} - - methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -565,19 +562,13 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodFromContext(ctx context.Context) MethodCtx { - name, _ := ctx.Value(MethodNameCtxKey).(string) - service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) +func GetMethodCtx(r *http.Request) (MethodCtx, bool) { + ctx, ok := methodAnnotations[r.URL.Path] if !ok { - annotations = map[string]string{} + return MethodCtx{}, false } - return MethodCtx{ - Name: name, - Service: service, - Annotations: annotations, - } + return ctx, true } diff --git a/helpers.go.tmpl b/helpers.go.tmpl index cbf995d..ec6aa6f 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -32,8 +32,6 @@ var ( ServiceNameCtxKey = &contextKey{"ServiceName"} MethodNameCtxKey = &contextKey{"MethodName"} - - methodAnnotationsCtxKey = &contextKey{"MethodAnnotations"} ) func ServiceNameFromContext(ctx context.Context) string { @@ -51,19 +49,13 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func MethodFromContext(ctx context.Context) MethodCtx { - name, _ := ctx.Value(MethodNameCtxKey).(string) - service, _ := ctx.Value(ServiceNameCtxKey).(string) - annotations, ok := ctx.Value(methodAnnotationsCtxKey).(map[string]string) +func GetMethodCtx(r *http.Request) (MethodCtx, bool) { + ctx, ok := methodAnnotations[r.URL.Path] if !ok { - annotations = map[string]string{} + return MethodCtx{}, false } - return MethodCtx{ - Name: name, - Service: service, - Annotations: annotations, - } + return ctx, true } {{ if $opts.server}} diff --git a/server.go.tmpl b/server.go.tmpl index 6589f00..822cf58 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -42,7 +42,6 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "{{.Name}}") - ctx = context.WithValue(ctx, methodAnnotationsCtxKey, methodAnnotations[r.URL.Path]) var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { From be323310f3bac422134e5f6b98942ab90e97a308 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Tue, 1 Oct 2024 14:58:08 +0200 Subject: [PATCH 16/18] dont export method --- _examples/golang-basics/example.gen.go | 16 +++++++++------- _examples/golang-imports/api.gen.go | 16 +++++++++------- helpers.go.tmpl | 12 +++++++----- types.go.tmpl | 2 +- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 981db09..8301029 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ // example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-15-g3735deb with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-17-gc0bce63 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -161,7 +161,7 @@ type ComplexType struct { } var ( - methodAnnotations = map[string]MethodCtx{ + methods = map[string]method{ "/rpc/ExampleService/Ping": { Name: "Ping", Service: "ExampleService", @@ -796,7 +796,7 @@ func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { // Helpers // -type MethodCtx struct { +type method struct { Name string Service string Annotations map[string]string @@ -836,13 +836,15 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func GetMethodCtx(r *http.Request) (MethodCtx, bool) { - ctx, ok := methodAnnotations[r.URL.Path] +func MethodCtx(ctx context.Context) (method, bool) { + req := RequestFromContext(ctx) + + m, ok := methods[req.URL.Path] if !ok { - return MethodCtx{}, false + return method{}, false } - return ctx, true + return m, true } func ResponseWriterFromContext(ctx context.Context) http.ResponseWriter { diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index ea7cd4c..c99e2d0 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-15-g3735deb with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-17-gc0bce63 with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -85,7 +85,7 @@ func (x *Location) Is(values ...Location) bool { } var ( - methodAnnotations = map[string]MethodCtx{ + methods = map[string]method{ "/rpc/ExampleAPI/Ping": { Name: "Ping", Service: "ExampleAPI", @@ -522,7 +522,7 @@ func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { // Helpers // -type MethodCtx struct { +type method struct { Name string Service string Annotations map[string]string @@ -562,13 +562,15 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func GetMethodCtx(r *http.Request) (MethodCtx, bool) { - ctx, ok := methodAnnotations[r.URL.Path] +func MethodCtx(ctx context.Context) (method, bool) { + req := RequestFromContext(ctx) + + m, ok := methods[req.URL.Path] if !ok { - return MethodCtx{}, false + return method{}, false } - return ctx, true + return m, true } diff --git a/helpers.go.tmpl b/helpers.go.tmpl index ec6aa6f..e703c24 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -5,7 +5,7 @@ // Helpers // -type MethodCtx struct { +type method struct { Name string Service string Annotations map[string]string @@ -49,13 +49,15 @@ func RequestFromContext(ctx context.Context) *http.Request { return r } -func GetMethodCtx(r *http.Request) (MethodCtx, bool) { - ctx, ok := methodAnnotations[r.URL.Path] +func MethodCtx(ctx context.Context) (method, bool) { + req := RequestFromContext(ctx) + + m, ok := methods[req.URL.Path] if !ok { - return MethodCtx{}, false + return method{}, false } - return ctx, true + return m, true } {{ if $opts.server}} diff --git a/types.go.tmpl b/types.go.tmpl index adb77d8..a9cefeb 100644 --- a/types.go.tmpl +++ b/types.go.tmpl @@ -30,7 +30,7 @@ {{- end }} var ( - methodAnnotations = map[string]MethodCtx{ + methods = map[string]method{ {{- range $_, $service := $services -}} {{- range $_, $method := $service.Methods }} "/rpc/{{$service.Name}}/{{$method.Name}}": { From 89a072e3252b99b48aa1de0dbd9729ce62357778 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Tue, 1 Oct 2024 15:07:55 +0200 Subject: [PATCH 17/18] set updated ctx to Request --- _examples/golang-basics/example.gen.go | 2 ++ _examples/golang-imports/api.gen.go | 2 ++ server.go.tmpl | 2 ++ 3 files changed, 6 insertions(+) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index 8301029..ada9102 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -272,6 +272,8 @@ func (s *exampleServiceServer) ServeHTTP(w http.ResponseWriter, r *http.Request) ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleService") + r = r.WithContext(ctx) + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleService/Ping": diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index c99e2d0..fc805bb 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -172,6 +172,8 @@ func (s *exampleAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "ExampleAPI") + r = r.WithContext(ctx) + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { case "/rpc/ExampleAPI/Ping": diff --git a/server.go.tmpl b/server.go.tmpl index 822cf58..4bb6a89 100644 --- a/server.go.tmpl +++ b/server.go.tmpl @@ -43,6 +43,8 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, HTTPRequestCtxKey, r) ctx = context.WithValue(ctx, ServiceNameCtxKey, "{{.Name}}") + r = r.WithContext(ctx) + var handler func(ctx context.Context, w http.ResponseWriter, r *http.Request) switch r.URL.Path { {{- range $_, $method := $service.Methods}} From 17954ee3fd9eed1483858f7688d41738f8b413d1 Mon Sep 17 00:00:00 2001 From: Lukas Jenicek Date: Wed, 2 Oct 2024 12:37:25 +0200 Subject: [PATCH 18/18] check if req != nil --- _examples/golang-basics/example.gen.go | 5 ++++- _examples/golang-imports/api.gen.go | 5 ++++- helpers.go.tmpl | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/_examples/golang-basics/example.gen.go b/_examples/golang-basics/example.gen.go index ada9102..204d609 100644 --- a/_examples/golang-basics/example.gen.go +++ b/_examples/golang-basics/example.gen.go @@ -1,6 +1,6 @@ // example v0.0.1 05b7a5c86b98738f4fe6ce9bb1fccd4af064847a // -- -// Code generated by webrpc-gen@v0.19.3-17-gc0bce63 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-1-g8d197ff with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=example.ridl -target=../../../gen-golang -pkg=main -server -client -legacyErrors -fixEmptyArrays -out=./example.gen.go package main @@ -840,6 +840,9 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodCtx(ctx context.Context) (method, bool) { req := RequestFromContext(ctx) + if req == nil { + return method{}, false + } m, ok := methods[req.URL.Path] if !ok { diff --git a/_examples/golang-imports/api.gen.go b/_examples/golang-imports/api.gen.go index fc805bb..ef953a8 100644 --- a/_examples/golang-imports/api.gen.go +++ b/_examples/golang-imports/api.gen.go @@ -1,6 +1,6 @@ // example-api-service v1.0.0 cae4e128f4fb4c938bfe1ea312deeea3dfd6b6af // -- -// Code generated by webrpc-gen@v0.19.3-17-gc0bce63 with ../../../gen-golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3-1-g8d197ff with ../../../gen-golang generator. DO NOT EDIT. // // webrpc-gen -schema=./proto/api.ridl -target=../../../gen-golang -out=./api.gen.go -pkg=main -server -client -legacyErrors=true -fmt=false package main @@ -566,6 +566,9 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodCtx(ctx context.Context) (method, bool) { req := RequestFromContext(ctx) + if req == nil { + return method{}, false + } m, ok := methods[req.URL.Path] if !ok { diff --git a/helpers.go.tmpl b/helpers.go.tmpl index e703c24..ae0c538 100644 --- a/helpers.go.tmpl +++ b/helpers.go.tmpl @@ -51,6 +51,9 @@ func RequestFromContext(ctx context.Context) *http.Request { func MethodCtx(ctx context.Context) (method, bool) { req := RequestFromContext(ctx) + if req == nil { + return method{}, false + } m, ok := methods[req.URL.Path] if !ok {