Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/clients/go/CHANGELOG.md.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v{{packageVersion}}...HEAD)

- feat: add support for custom headers per request. See [documentation](https://github.com/openfga/go-sdk#custom-headers).

## {{packageVersion}}

### [{{packageVersion}}](https://{{gitHost}}/{{gitUserId}}/{{gitRepoId}}/compare/v0.7.1...v{{packageVersion}}) (2025-09-15)
Expand Down
6 changes: 6 additions & 0 deletions config/clients/go/config.overrides.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
"destinationFilename": "client/errors.go",
"templateType": "SupportingFiles"
},
"client/client_headers_test.go": {
"destinationFilename": "client/client_headers_test.go"
},
"api_headers_test.go": {
"destinationFilename": "api_headers_test.go"
},
"api_client_test.mustache": {
"destinationFilename": "api_client_test.go",
"templateType": "SupportingFiles"
Expand Down
40 changes: 40 additions & 0 deletions config/clients/go/template/README_initializing.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,43 @@ func main() {
}
}
```

### Custom Headers

#### Default Headers
You can set default headers that will be sent with every request during client initialization:

```golang
fgaClient, err := client.NewSdkClient(&client.ClientConfiguration{
ApiUrl: os.Getenv("FGA_API_URL"),
StoreId: os.Getenv("FGA_STORE_ID"),
AuthorizationModelId: os.Getenv("FGA_MODEL_ID"),
DefaultHeaders: map[string]string{
"X-Custom-Header": "default-value",
"X-Request-Source": "my-app",
},
})
```

#### Per-Request Headers

You can also send custom headers on a per-request basis by using the `Options` parameter. Custom headers will override any default headers set in the client configuration.

```golang
// Add custom headers to a specific request
checkResponse, err := fgaClient.Check(context.Background()).
Body(client.ClientCheckRequest{
User: "user:anne",
Relation: "viewer",
Object: "document:roadmap",
}).
Options(client.ClientCheckOptions{
RequestOptions: client.RequestOptions{
Headers: map[string]string{
"X-Request-ID": "123e4567-e89b-12d3-a456-426614174000",
"X-Custom-Header": "custom-value", // these override any default headers set
},
},
}).
Execute()
```
17 changes: 17 additions & 0 deletions config/clients/go/template/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ var (
)
{{#generateInterfaces}}

type RequestOptions struct {
Headers map[string]string `json:"headers,omitempty"`
}

type {{classname}} interface {
{{#operation}}

Expand Down Expand Up @@ -61,13 +65,20 @@ type {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request s
{{#allParams}}
{{paramName}} {{^isPathParam}}*{{/isPathParam}}{{{dataType}}}
{{/allParams}}
options RequestOptions
}

{{#allParams}}{{^isPathParam}}
func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) {{vendorExtensions.x-export-param-name}}({{paramName}} {{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
r.{{paramName}} = &{{paramName}}
return r
}{{/isPathParam}}{{/allParams}}

func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) Options(options RequestOptions) {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request {
r.options = options
return r
}

func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}Api{{operationId}}Request) Execute() ({{#returnType}}{{{.}}}, {{/returnType}}*http.Response, error) {
return r.ApiService.{{nickname}}Execute(r)
}
Expand Down Expand Up @@ -281,6 +292,7 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class
// body params
requestBody = r.{{paramName}}
{{/bodyParams}}

{{#authMethods}}
{{#isApiKey}}
{{^isKeyInCookie}}
Expand Down Expand Up @@ -318,6 +330,11 @@ func (a *{{{classname}}}Service) {{nickname}}Execute(r {{#structPrefix}}{{&class
{{/isApiKey}}
{{/authMethods}}

// if any override headers were in the options, set them now
for header, val := range r.options.Headers {
localVarHeaderParams[header] = val
}

retryParams := a.client.cfg.RetryParams
for i := 0; i < retryParams.MaxRetry+1; i++ {
req, err := a.client.prepareRequest(r.ctx, path, httpMethod, requestBody, localVarHeaderParams, localVarQueryParams)
Expand Down
4 changes: 3 additions & 1 deletion config/clients/go/template/api_client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ func (c *APIClient) prepareRequest(
localVarRequest.Header.Set("User-Agent", c.cfg.UserAgent)

for header, value := range c.cfg.DefaultHeaders {
localVarRequest.Header.Set(header, value)
if localVarRequest.Header.Get(header) == "" {
localVarRequest.Header.Set(header, value)
}
}

if ctx != nil {
Expand Down
Loading
Loading