Skip to content

Commit

Permalink
Add client and server versions of generators (webrpc, schema and ridl…
Browse files Browse the repository at this point in the history
… schema) (#72)

* add client and server versions of generators (webrpc, schema and ridl schema)

* rename to WebRpc

* improve naming

* generate only if includeHeaders option is set

* rename to Webrpc

* use one function to parse headers

* rename all occurences to Webrpc

* rename to webrpcHeader

* fix conditions in main.tmpl

* regenerate examples
  • Loading branch information
LukasJenicek authored Oct 18, 2024
1 parent 5275eca commit 8a2785a
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Change any of the following values by passing `-option="Value"` CLI flag to `web
| `-fixEmptyArrays` | `false` | force empty array `[]` instead of `null` in JSON (see Go [#27589][go27589]) | v0.13.0 |
| `-errorStackTrace` | `false` | enables error stack traces | v0.14.0 |
| `-legacyErrors` | `false` | enable legacy errors (v0.10.0 or older) | v0.11.0 |
| `-webrpcHeader` | `true` | enable client send webrpc version in http headers | v0.16.0 |

Example:
```
Expand Down
77 changes: 72 additions & 5 deletions _examples/golang-basics/example.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion _examples/golang-basics/example.ridl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ webrpc = v1 # version of webrpc schema format (ridl or json)

name = example # name of your backend app
version = v0.0.1 # version of your schema


# user role
# which defines which type of operations user can do
Expand Down Expand Up @@ -69,6 +68,8 @@ struct Version
- webrpcVersion: string
- schemaVersion: string
- schemaHash: string
- clientGenVersion: GenVersions
- serverGenVersion: GenVersions

struct ComplexType
- meta: map<string,any>
Expand All @@ -81,6 +82,12 @@ struct ComplexType
- mapOfUsers: map<string,User>
- user: User

struct GenVersions
- WebrpcGenVersion: string
- TmplTarget: string
- TmplVersion: string
- SchemaVersion: string

error 500100 MissingArgument "missing argument"
error 500101 InvalidUsername "invalid username"
error 400100 MemoryFull "system memory is full"
Expand Down
8 changes: 8 additions & 0 deletions _examples/golang-basics/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ func TestStatus(t *testing.T) {
assert.NoError(t, err)
}

func TestVersion(t *testing.T) {
version, err := client.Version(context.Background())

assert.NoError(t, err)
assert.NotNil(t, version.ClientGenVersion)
assert.NotNil(t, version.ServerGenVersion)
}

func TestGetUser(t *testing.T) {
{
arg1 := map[string]string{"a": "1"}
Expand Down
24 changes: 24 additions & 0 deletions _examples/golang-basics/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,34 @@ func (rpc *ExampleServiceRPC) Status(ctx context.Context) (bool, error) {
}

func (rpc *ExampleServiceRPC) Version(ctx context.Context) (*Version, error) {
resp := ResponseWriterFromContext(ctx)
serverVersions, err := VersionFromHeader(resp.Header())
if err != nil {
return nil, fmt.Errorf("parse server webrpc gen versions: %w", err)
}

req := RequestFromContext(ctx)
clientVersions, err := VersionFromHeader(req.Header)
if err != nil {
return nil, fmt.Errorf("parse client webrpc gen versions: %w", err)
}

return &Version{
WebrpcVersion: WebRPCVersion(),
SchemaVersion: WebRPCSchemaVersion(),
SchemaHash: WebRPCSchemaHash(),
ClientGenVersion: &GenVersions{
WebrpcGenVersion: clientVersions.WebrpcGenVersion,
TmplTarget: clientVersions.CodeGenName,
TmplVersion: clientVersions.CodeGenVersion,
SchemaVersion: clientVersions.CodeGenVersion,
},
ServerGenVersion: &GenVersions{
WebrpcGenVersion: serverVersions.WebrpcGenVersion,
TmplTarget: serverVersions.CodeGenName,
TmplVersion: serverVersions.CodeGenVersion,
SchemaVersion: serverVersions.CodeGenVersion,
},
}, nil
}

Expand Down
58 changes: 58 additions & 0 deletions _examples/golang-imports/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions client.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType
}
req.Header.Set("Accept", contentType)
req.Header.Set("Content-Type", contentType)
{{- if eq $opts.webrpcHeader true }}
req.Header.Set(WebrpcHeader, WebrpcHeaderValue)
{{- end }}
if headers, ok := HTTPRequestHeaders(ctx); ok {
for k := range headers {
for _, v := range headers[k] {
Expand Down
56 changes: 56 additions & 0 deletions main.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
{{- set $opts "fixEmptyArrays" (ternary (in .Opts.fixEmptyArrays "" "true") true false) -}}
{{- set $opts "errorStackTrace" (ternary (in .Opts.errorStackTrace "" "true") true false) -}}
{{- set $opts "legacyErrors" (ternary (in .Opts.legacyErrors "" "true") true false) -}}
{{- set $opts "webrpcHeader" (ternary (eq (default .Opts.webrpcHeader "true") "false") false true) -}}

{{- $typePrefix := (last (split "/" $opts.importTypesFrom)) -}}
{{- if ne $typePrefix "" -}}
Expand Down Expand Up @@ -81,6 +82,10 @@ package {{get $opts "pkg"}}

{{template "imports" dict "Types" .Types "Opts" $opts }}

const WebrpcHeader = "Webrpc"

const WebrpcHeaderValue = "{{ .WebrpcHeader }}"

// WebRPC description and code-gen version
func WebRPCVersion() string {
return "{{.WebrpcVersion}}"
Expand All @@ -96,6 +101,57 @@ func WebRPCSchemaHash() string {
return "{{.SchemaHash}}"
}

type WebrpcGenVersions struct {
WebrpcGenVersion string
CodeGenName string
CodeGenVersion string
SchemaName string
SchemaVersion string
}

func VersionFromHeader(h http.Header) (*WebrpcGenVersions, error) {
if h.Get(WebrpcHeader) == "" {
return nil, fmt.Errorf("header is empty or missing")
}

versions, err := parseWebrpcGenVersions(h.Get(WebrpcHeader))
if err != nil {
return nil, fmt.Errorf("webrpc header is invalid: %w", err)
}

return versions, nil
}

func parseWebrpcGenVersions(header string) (*WebrpcGenVersions, error) {
versions := strings.Split(header, ";")
if len(versions) < 3 {
return nil, fmt.Errorf("expected at least 3 parts while parsing webrpc header: %v", header)
}

_, webrpcGenVersion, ok := strings.Cut(versions[0], "@")
if !ok {
return nil, fmt.Errorf("webrpc gen version could not be parsed from: %s", versions[0])
}

tmplTarget, tmplVersion, ok := strings.Cut(versions[1], "@")
if !ok {
return nil, fmt.Errorf("tmplTarget and tmplVersion could not be parsed from: %s", versions[1])
}

schemaName, schemaVersion, ok := strings.Cut(versions[2], "@")
if !ok {
return nil, fmt.Errorf("schema name and schema version could not be parsed from: %s", versions[2])
}

return &WebrpcGenVersions{
WebrpcGenVersion: webrpcGenVersion,
CodeGenName: tmplTarget,
CodeGenVersion: tmplVersion,
SchemaName: schemaName,
SchemaVersion: schemaVersion,
}, nil
}

{{- printf "\n" -}}

{{- if eq $opts.importTypesFrom "" }}
Expand Down
2 changes: 2 additions & 0 deletions server.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func (s *{{$serviceName}}) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}()

w.Header().Set(WebrpcHeader, WebrpcHeaderValue)

ctx := r.Context()
ctx = context.WithValue(ctx, HTTPResponseWriterCtxKey, w)
ctx = context.WithValue(ctx, HTTPRequestCtxKey, r)
Expand Down

0 comments on commit 8a2785a

Please sign in to comment.