From 185a14a582e8cc3b90c966cefd3e863c0e3b8bfb Mon Sep 17 00:00:00 2001 From: Armando Belardo <11140328+armandobelardo@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:57:39 -0500 Subject: [PATCH] feat, python: support envvar scanning for headers (#3064) --- generators/python/poetry.lock | 38 ++-- generators/python/pyproject.toml | 2 +- generators/python/sdk/CHANGELOG.md | 33 ++++ generators/python/sdk/VERSION | 2 +- .../endpoint_function_generator.py | 22 ++- .../client_wrapper_generator.py | 1 + .../auth-environment-variables.txt | 186 +++++++++++++++++- .../v35-to-v34/migrateFromV35ToV34.ts | 2 +- .../v36-to-v35/migrateFromV36ToV35.ts | 2 +- .../auth-environment-variables/ir.json | 175 +++++++++++++++- .../auth-environment-variables/ir.json | 175 +++++++++++++++- .../resources/service/service/service.py | 50 ++++- .../auth-environment-variables/service.go | 8 + .../auth-environment-variables/service.go | 3 + .../core/request_option.go | 21 +- .../option/request_option.go | 7 + .../auth-environment-variables/service.go | 8 + .../service/client.go | 39 ++++ ...AuthEnvironmentVariablesClientBuilder.java | 14 +- .../core/RequestOptions.java | 17 +- .../resources/service/ServiceClient.java | 40 ++++ .../service/requests/HeaderAuthRequest.java | 108 ++++++++++ .../resources/service/ServiceService.java | 10 +- .../auth-environment-variables/openapi.yml | 20 ++ .../collection.json | 36 ++++ .../src/seed/client.py | 18 ++ .../src/seed/core/client_wrapper.py | 12 +- .../src/seed/resources/service/client.py | 83 ++++++++ seed/python-sdk/seed.yml | 2 +- seed/python-sdk/websocket/src/seed/client.py | 34 ++++ .../websocket/src/seed/core/__init__.py | 3 + .../lib/requests.rb | 26 ++- .../seed_auth_environment_variables_client.rb | 10 +- .../service/client.rb | 48 +++++ .../service/service/ServiceService.d.ts | 5 + .../service/service/ServiceService.js | 27 +++ .../service/service/getWithHeader.d.ts | 9 + .../service/service/getWithHeader.js | 31 +++ .../resources/service/service/index.d.ts | 1 + .../resources/service/service/index.js | 3 +- .../auth-environment-variables/src/Client.ts | 3 +- .../src/api/resources/index.ts | 1 + .../api/resources/service/client/Client.ts | 61 +++++- .../src/api/resources/service/client/index.ts | 2 +- .../client/requests/HeaderAuthRequest.ts | 10 + .../service/client/requests/index.ts | 1 + .../resources/service/client/getWithHeader.ts | 13 ++ .../resources/service/client/index.ts | 1 + .../definition/api.yml | 4 + .../definition/service.yml | 13 ++ 50 files changed, 1373 insertions(+), 67 deletions(-) create mode 100644 seed/go-fiber/auth-environment-variables/service.go create mode 100644 seed/go-model/auth-environment-variables/service.go create mode 100644 seed/go-sdk/auth-environment-variables/service.go create mode 100644 seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/requests/HeaderAuthRequest.java create mode 100644 seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.d.ts create mode 100644 seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.js create mode 100644 seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/HeaderAuthRequest.ts create mode 100644 seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/index.ts create mode 100644 seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/getWithHeader.ts diff --git a/generators/python/poetry.lock b/generators/python/poetry.lock index 2729af55443..9a58f120224 100644 --- a/generators/python/poetry.lock +++ b/generators/python/poetry.lock @@ -192,14 +192,14 @@ url = "https://pypi.buildwithfern.com" reference = "fern-prod" [[package]] -name = "fern-fern-ir-v34" -version = "0.0.3363" +name = "fern-fern-ir-v36" +version = "0.0.3413" description = "" optional = false python-versions = ">=3.7,<4.0" files = [ - {file = "fern_fern_ir_v34-0.0.3363-py3-none-any.whl", hash = "sha256:032407a2c314f6f6f04b5d76162bb010b22e91e14997150ea5188f92c8d53827"}, - {file = "fern_fern_ir_v34-0.0.3363.tar.gz", hash = "sha256:bee921c30e31556da967770e1a912c269d9cb24e3a03c4239f7094613ca4246b"}, + {file = "fern_fern_ir_v36-0.0.3413-py3-none-any.whl", hash = "sha256:13b93f0790f0b381525443520234e8eda7fad191834bbb69783414f46faf9faf"}, + {file = "fern_fern_ir_v36-0.0.3413.tar.gz", hash = "sha256:a6244797e848e7e2ee32eb5f63ac4a02bdb996f35cf6702c756755aede799c2f"}, ] [package.dependencies] @@ -732,19 +732,19 @@ jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] [[package]] name = "setuptools" -version = "69.1.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.0-py3-none-any.whl", hash = "sha256:c054629b81b946d63a9c6e732bc8b2513a7c3ea645f11d0139a2191d735c60c6"}, - {file = "setuptools-69.1.0.tar.gz", hash = "sha256:850894c4195f09c4ed30dba56213bf7c3f21d86ed6bdaafb5df5972593bfc401"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" @@ -791,13 +791,13 @@ test = ["django (>=1.10.6)", "nose", "pytest (>=4.6)", "pytest-cov", "six"] [[package]] name = "sniffio" -version = "1.3.0" +version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] [[package]] @@ -861,24 +861,24 @@ files = [ [[package]] name = "typing-extensions" -version = "4.9.0" +version = "4.10.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, - {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] [[package]] name = "virtualenv" -version = "20.25.0" +version = "20.25.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, - {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, ] [package.dependencies] @@ -939,4 +939,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "d4d7aedb66a22a387833670cedbb75b0ee3b76761e89bf726810c08ae1a32ad2" +content-hash = "ba979504c145a05a48e778d2868447dcddad0e9ff0d594c15708b6f8c4d53cc1" diff --git a/generators/python/pyproject.toml b/generators/python/pyproject.toml index 6180c1bdaf4..b2dc70e4186 100644 --- a/generators/python/pyproject.toml +++ b/generators/python/pyproject.toml @@ -10,7 +10,7 @@ pydantic = "^1.9.2" typer = {extras = ["all"], version = "^0.6.1"} fern-fern-generator-exec-sdk = {version = "0.0.570", source = "fern-prod"} ordered-set = "^4.1.0" -fern_fern_ir_v34 = "^0.0.3363" +fern_fern_ir_v36 = "^0.0.3413" [tool.poetry.dev-dependencies] pytest = "^7.4.2" diff --git a/generators/python/sdk/CHANGELOG.md b/generators/python/sdk/CHANGELOG.md index e3e5754f1fb..40437fa32fe 100644 --- a/generators/python/sdk/CHANGELOG.md +++ b/generators/python/sdk/CHANGELOG.md @@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.11.6] - 2024-02-26 + +- Improvement: You can now specify envvars to scan for headers, not just auth scheme headers. + ``` + # OpenAPI + x-fern-global-headers: + - header: x-api-key + name: api_key + optional: true + env: MY_API_KEY + ``` + ... or ... + ``` + # Fern Definition + getAllUsers: + method: GET + path: /all + request: + name: GetAllUsersRequest + headers: + X-API-KEY: string + env: MY_API_KEY + ``` + the generated client will look like + + ```python + import os + + class Client: + + def __init__(self, *, apiKey: str = os.getenv("MY_API_KEY")) + ``` + ## [0.11.5] - 2024-02-23 - Fix: Fix the usage of ApiError when leveraging auth envvars, when the schema for ApiError was changed, this usage was missed in the update. diff --git a/generators/python/sdk/VERSION b/generators/python/sdk/VERSION index 62d5dbdf3c7..e5cbde33e62 100644 --- a/generators/python/sdk/VERSION +++ b/generators/python/sdk/VERSION @@ -1 +1 @@ -0.11.5 +0.11.6 diff --git a/generators/python/src/fern_python/generators/sdk/client_generator/endpoint_function_generator.py b/generators/python/src/fern_python/generators/sdk/client_generator/endpoint_function_generator.py index 179da041009..c9f61acc820 100644 --- a/generators/python/src/fern_python/generators/sdk/client_generator/endpoint_function_generator.py +++ b/generators/python/src/fern_python/generators/sdk/client_generator/endpoint_function_generator.py @@ -199,14 +199,28 @@ def _get_endpoint_named_parameters( for header in service.headers + endpoint.headers: if not self._is_header_literal(header): + header_type_hint = self._context.pydantic_generator_context.get_type_hint_for_type_reference( + header.value_type, + in_endpoint=True, + ) + if header.env is not None: + header_type_hint = AST.TypeHint.optional(header_type_hint) parameters.append( AST.NamedFunctionParameter( name=get_parameter_name(header.name.name), docs=header.docs, - type_hint=self._context.pydantic_generator_context.get_type_hint_for_type_reference( - header.value_type, - in_endpoint=True, - ), + type_hint=header_type_hint, + initializer=AST.Expression( + AST.FunctionInvocation( + function_definition=AST.Reference( + import_=AST.ReferenceImport(module=AST.Module.built_in(("os",))), + qualified_name_excluding_import=("getenv",), + ), + args=[AST.Expression(f'"{header.env}"')], + ) + ) + if header.env is not None + else None, ), ) diff --git a/generators/python/src/fern_python/generators/sdk/core_utilities/client_wrapper_generator.py b/generators/python/src/fern_python/generators/sdk/core_utilities/client_wrapper_generator.py index 586a120b61b..0025021a1bb 100644 --- a/generators/python/src/fern_python/generators/sdk/core_utilities/client_wrapper_generator.py +++ b/generators/python/src/fern_python/generators/sdk/core_utilities/client_wrapper_generator.py @@ -421,6 +421,7 @@ def _get_constructor_info(self) -> ConstructorInfo: f'{constructor_parameter_name}="YOUR_{header.name.name.screaming_snake_case.safe_name}"', ), header_key=header.name.wire_value, + environment_variable=header.env, ) ) diff --git a/packages/cli/generation/ir-generator/src/__test__/__snapshots__/auth-environment-variables.txt b/packages/cli/generation/ir-generator/src/__test__/__snapshots__/auth-environment-variables.txt index a5642b637bb..a6f415ef2af 100644 --- a/packages/cli/generation/ir-generator/src/__test__/__snapshots__/auth-environment-variables.txt +++ b/packages/cli/generation/ir-generator/src/__test__/__snapshots__/auth-environment-variables.txt @@ -91,7 +91,39 @@ exports[`generate IR 1`] = ` "type": "statusCode", }, "errors": {}, - "headers": [], + "headers": [ + { + "availability": null, + "docs": null, + "env": "ANOTHER_ENV_VAR", + "name": { + "name": { + "camelCase": { + "safeName": "xAnotherHeader", + "unsafeName": "xAnotherHeader", + }, + "originalName": "X-Another-Header", + "pascalCase": { + "safeName": "XAnotherHeader", + "unsafeName": "XAnotherHeader", + }, + "screamingSnakeCase": { + "safeName": "X_ANOTHER_HEADER", + "unsafeName": "X_ANOTHER_HEADER", + }, + "snakeCase": { + "safeName": "x_another_header", + "unsafeName": "x_another_header", + }, + }, + "wireValue": "X-Another-Header", + }, + "valueType": { + "_type": "primitive", + "primitive": "STRING", + }, + }, + ], "idempotencyHeaders": [], "pathParameters": [], "rootPackage": { @@ -115,7 +147,7 @@ exports[`generate IR 1`] = ` "sdkConfig": { "hasFileDownloadEndpoints": false, "hasStreamingEndpoints": false, - "isAuthMandatory": true, + "isAuthMandatory": false, "platformHeaders": { "language": "X-Fern-Language", "sdkName": "X-Fern-SDK-Name", @@ -192,6 +224,156 @@ exports[`generate IR 1`] = ` }, "sdkRequest": null, }, + { + "allPathParameters": [], + "auth": false, + "availability": null, + "baseUrl": null, + "displayName": null, + "docs": "GET request with custom api key", + "errors": [], + "examples": [], + "fullPath": { + "head": "apiKeyInHeader", + "parts": [], + }, + "headers": [ + { + "availability": null, + "docs": "Specifies the endpoint key.", + "env": "MY_HEADER_ENV", + "name": { + "name": { + "camelCase": { + "safeName": "xEndpointHeader", + "unsafeName": "xEndpointHeader", + }, + "originalName": "X-Endpoint-Header", + "pascalCase": { + "safeName": "XEndpointHeader", + "unsafeName": "XEndpointHeader", + }, + "screamingSnakeCase": { + "safeName": "X_ENDPOINT_HEADER", + "unsafeName": "X_ENDPOINT_HEADER", + }, + "snakeCase": { + "safeName": "x_endpoint_header", + "unsafeName": "x_endpoint_header", + }, + }, + "wireValue": "X-Endpoint-Header", + }, + "valueType": { + "_type": "primitive", + "primitive": "STRING", + }, + }, + ], + "id": "endpoint_service.getWithHeader", + "idempotent": false, + "method": "GET", + "name": { + "camelCase": { + "safeName": "getWithHeader", + "unsafeName": "getWithHeader", + }, + "originalName": "getWithHeader", + "pascalCase": { + "safeName": "GetWithHeader", + "unsafeName": "GetWithHeader", + }, + "screamingSnakeCase": { + "safeName": "GET_WITH_HEADER", + "unsafeName": "GET_WITH_HEADER", + }, + "snakeCase": { + "safeName": "get_with_header", + "unsafeName": "get_with_header", + }, + }, + "pagination": null, + "path": { + "head": "/apiKeyInHeader", + "parts": [], + }, + "pathParameters": [], + "queryParameters": [], + "requestBody": null, + "response": { + "type": "json", + "value": { + "docs": null, + "responseBodyType": { + "_type": "primitive", + "primitive": "STRING", + }, + "type": "response", + }, + }, + "sdkRequest": { + "requestParameterName": { + "camelCase": { + "safeName": "request", + "unsafeName": "request", + }, + "originalName": "request", + "pascalCase": { + "safeName": "Request", + "unsafeName": "Request", + }, + "screamingSnakeCase": { + "safeName": "REQUEST", + "unsafeName": "REQUEST", + }, + "snakeCase": { + "safeName": "request", + "unsafeName": "request", + }, + }, + "shape": { + "bodyKey": { + "camelCase": { + "safeName": "body", + "unsafeName": "body", + }, + "originalName": "body", + "pascalCase": { + "safeName": "Body", + "unsafeName": "Body", + }, + "screamingSnakeCase": { + "safeName": "BODY", + "unsafeName": "BODY", + }, + "snakeCase": { + "safeName": "body", + "unsafeName": "body", + }, + }, + "type": "wrapper", + "wrapperName": { + "camelCase": { + "safeName": "headerAuthRequest", + "unsafeName": "headerAuthRequest", + }, + "originalName": "HeaderAuthRequest", + "pascalCase": { + "safeName": "HeaderAuthRequest", + "unsafeName": "HeaderAuthRequest", + }, + "screamingSnakeCase": { + "safeName": "HEADER_AUTH_REQUEST", + "unsafeName": "HEADER_AUTH_REQUEST", + }, + "snakeCase": { + "safeName": "header_auth_request", + "unsafeName": "header_auth_request", + }, + }, + }, + }, + }, ], "headers": [], "name": { diff --git a/packages/cli/generation/ir-migrations/src/migrations/v35-to-v34/migrateFromV35ToV34.ts b/packages/cli/generation/ir-migrations/src/migrations/v35-to-v34/migrateFromV35ToV34.ts index 8d901ae49bc..60d8811e647 100644 --- a/packages/cli/generation/ir-migrations/src/migrations/v35-to-v34/migrateFromV35ToV34.ts +++ b/packages/cli/generation/ir-migrations/src/migrations/v35-to-v34/migrateFromV35ToV34.ts @@ -25,7 +25,7 @@ export const V35_TO_V34_MIGRATION: IrMigration< [GeneratorName.OPENAPI]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.STOPLIGHT]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.POSTMAN]: GeneratorWasNeverUpdatedToConsumeNewIR, - [GeneratorName.PYTHON_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR, + [GeneratorName.PYTHON_SDK]: "0.11.6", [GeneratorName.GO_FIBER]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.GO_MODEL]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.GO_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR, diff --git a/packages/cli/generation/ir-migrations/src/migrations/v36-to-v35/migrateFromV36ToV35.ts b/packages/cli/generation/ir-migrations/src/migrations/v36-to-v35/migrateFromV36ToV35.ts index 99657a0fa92..7e4d8e01299 100644 --- a/packages/cli/generation/ir-migrations/src/migrations/v36-to-v35/migrateFromV36ToV35.ts +++ b/packages/cli/generation/ir-migrations/src/migrations/v36-to-v35/migrateFromV36ToV35.ts @@ -25,7 +25,7 @@ export const V36_TO_V35_MIGRATION: IrMigration< [GeneratorName.OPENAPI]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.STOPLIGHT]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.POSTMAN]: GeneratorWasNeverUpdatedToConsumeNewIR, - [GeneratorName.PYTHON_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR, + [GeneratorName.PYTHON_SDK]: "0.11.6", [GeneratorName.GO_FIBER]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.GO_MODEL]: GeneratorWasNeverUpdatedToConsumeNewIR, [GeneratorName.GO_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR, diff --git a/seed/csharp-model/auth-environment-variables/ir.json b/seed/csharp-model/auth-environment-variables/ir.json index fe90e23b12c..cf89fb806cc 100644 --- a/seed/csharp-model/auth-environment-variables/ir.json +++ b/seed/csharp-model/auth-environment-variables/ir.json @@ -53,7 +53,36 @@ } ] }, - "headers": [], + "headers": [ + { + "name": { + "name": { + "originalName": "X-Another-Header", + "camelCase": { + "unsafeName": "xAnotherHeader", + "safeName": "xAnotherHeader" + }, + "snakeCase": { + "unsafeName": "x_another_header", + "safeName": "x_another_header" + }, + "screamingSnakeCase": { + "unsafeName": "X_ANOTHER_HEADER", + "safeName": "X_ANOTHER_HEADER" + }, + "pascalCase": { + "unsafeName": "XAnotherHeader", + "safeName": "XAnotherHeader" + } + }, + "wireValue": "X-Another-Header" + }, + "valueType": { + "primitive": "STRING", + "type": "primitive" + } + } + ], "idempotencyHeaders": [], "types": {}, "errors": {}, @@ -160,6 +189,148 @@ "errors": [], "examples": [], "docs": "GET request with custom api key" + }, + { + "id": "endpoint_service.getWithHeader", + "name": { + "originalName": "getWithHeader", + "camelCase": { + "unsafeName": "getWithHeader", + "safeName": "getWithHeader" + }, + "snakeCase": { + "unsafeName": "get_with_header", + "safeName": "get_with_header" + }, + "screamingSnakeCase": { + "unsafeName": "GET_WITH_HEADER", + "safeName": "GET_WITH_HEADER" + }, + "pascalCase": { + "unsafeName": "GetWithHeader", + "safeName": "GetWithHeader" + } + }, + "auth": false, + "idempotent": false, + "method": "GET", + "path": { + "head": "/apiKeyInHeader", + "parts": [] + }, + "fullPath": { + "head": "apiKeyInHeader", + "parts": [] + }, + "pathParameters": [], + "allPathParameters": [], + "queryParameters": [], + "headers": [ + { + "name": { + "name": { + "originalName": "X-Endpoint-Header", + "camelCase": { + "unsafeName": "xEndpointHeader", + "safeName": "xEndpointHeader" + }, + "snakeCase": { + "unsafeName": "x_endpoint_header", + "safeName": "x_endpoint_header" + }, + "screamingSnakeCase": { + "unsafeName": "X_ENDPOINT_HEADER", + "safeName": "X_ENDPOINT_HEADER" + }, + "pascalCase": { + "unsafeName": "XEndpointHeader", + "safeName": "XEndpointHeader" + } + }, + "wireValue": "X-Endpoint-Header" + }, + "valueType": { + "primitive": "STRING", + "type": "primitive" + }, + "docs": "Specifies the endpoint key." + } + ], + "sdkRequest": { + "shape": { + "type": "wrapper", + "wrapperName": { + "originalName": "HeaderAuthRequest", + "camelCase": { + "unsafeName": "headerAuthRequest", + "safeName": "headerAuthRequest" + }, + "snakeCase": { + "unsafeName": "header_auth_request", + "safeName": "header_auth_request" + }, + "screamingSnakeCase": { + "unsafeName": "HEADER_AUTH_REQUEST", + "safeName": "HEADER_AUTH_REQUEST" + }, + "pascalCase": { + "unsafeName": "HeaderAuthRequest", + "safeName": "HeaderAuthRequest" + } + }, + "bodyKey": { + "originalName": "body", + "camelCase": { + "unsafeName": "body", + "safeName": "body" + }, + "snakeCase": { + "unsafeName": "body", + "safeName": "body" + }, + "screamingSnakeCase": { + "unsafeName": "BODY", + "safeName": "BODY" + }, + "pascalCase": { + "unsafeName": "Body", + "safeName": "Body" + } + } + }, + "requestParameterName": { + "originalName": "request", + "camelCase": { + "unsafeName": "request", + "safeName": "request" + }, + "snakeCase": { + "unsafeName": "request", + "safeName": "request" + }, + "screamingSnakeCase": { + "unsafeName": "REQUEST", + "safeName": "REQUEST" + }, + "pascalCase": { + "unsafeName": "Request", + "safeName": "Request" + } + } + }, + "response": { + "value": { + "type": "response", + "responseBodyType": { + "primitive": "STRING", + "type": "primitive" + } + }, + "type": "json" + }, + "errors": [], + "examples": [], + "docs": "GET request with custom api key" } ] } @@ -285,7 +456,7 @@ "hasEndpointsInTree": true }, "sdkConfig": { - "isAuthMandatory": true, + "isAuthMandatory": false, "hasStreamingEndpoints": false, "hasFileDownloadEndpoints": false, "platformHeaders": { diff --git a/seed/csharp-sdk/auth-environment-variables/ir.json b/seed/csharp-sdk/auth-environment-variables/ir.json index fe90e23b12c..cf89fb806cc 100644 --- a/seed/csharp-sdk/auth-environment-variables/ir.json +++ b/seed/csharp-sdk/auth-environment-variables/ir.json @@ -53,7 +53,36 @@ } ] }, - "headers": [], + "headers": [ + { + "name": { + "name": { + "originalName": "X-Another-Header", + "camelCase": { + "unsafeName": "xAnotherHeader", + "safeName": "xAnotherHeader" + }, + "snakeCase": { + "unsafeName": "x_another_header", + "safeName": "x_another_header" + }, + "screamingSnakeCase": { + "unsafeName": "X_ANOTHER_HEADER", + "safeName": "X_ANOTHER_HEADER" + }, + "pascalCase": { + "unsafeName": "XAnotherHeader", + "safeName": "XAnotherHeader" + } + }, + "wireValue": "X-Another-Header" + }, + "valueType": { + "primitive": "STRING", + "type": "primitive" + } + } + ], "idempotencyHeaders": [], "types": {}, "errors": {}, @@ -160,6 +189,148 @@ "errors": [], "examples": [], "docs": "GET request with custom api key" + }, + { + "id": "endpoint_service.getWithHeader", + "name": { + "originalName": "getWithHeader", + "camelCase": { + "unsafeName": "getWithHeader", + "safeName": "getWithHeader" + }, + "snakeCase": { + "unsafeName": "get_with_header", + "safeName": "get_with_header" + }, + "screamingSnakeCase": { + "unsafeName": "GET_WITH_HEADER", + "safeName": "GET_WITH_HEADER" + }, + "pascalCase": { + "unsafeName": "GetWithHeader", + "safeName": "GetWithHeader" + } + }, + "auth": false, + "idempotent": false, + "method": "GET", + "path": { + "head": "/apiKeyInHeader", + "parts": [] + }, + "fullPath": { + "head": "apiKeyInHeader", + "parts": [] + }, + "pathParameters": [], + "allPathParameters": [], + "queryParameters": [], + "headers": [ + { + "name": { + "name": { + "originalName": "X-Endpoint-Header", + "camelCase": { + "unsafeName": "xEndpointHeader", + "safeName": "xEndpointHeader" + }, + "snakeCase": { + "unsafeName": "x_endpoint_header", + "safeName": "x_endpoint_header" + }, + "screamingSnakeCase": { + "unsafeName": "X_ENDPOINT_HEADER", + "safeName": "X_ENDPOINT_HEADER" + }, + "pascalCase": { + "unsafeName": "XEndpointHeader", + "safeName": "XEndpointHeader" + } + }, + "wireValue": "X-Endpoint-Header" + }, + "valueType": { + "primitive": "STRING", + "type": "primitive" + }, + "docs": "Specifies the endpoint key." + } + ], + "sdkRequest": { + "shape": { + "type": "wrapper", + "wrapperName": { + "originalName": "HeaderAuthRequest", + "camelCase": { + "unsafeName": "headerAuthRequest", + "safeName": "headerAuthRequest" + }, + "snakeCase": { + "unsafeName": "header_auth_request", + "safeName": "header_auth_request" + }, + "screamingSnakeCase": { + "unsafeName": "HEADER_AUTH_REQUEST", + "safeName": "HEADER_AUTH_REQUEST" + }, + "pascalCase": { + "unsafeName": "HeaderAuthRequest", + "safeName": "HeaderAuthRequest" + } + }, + "bodyKey": { + "originalName": "body", + "camelCase": { + "unsafeName": "body", + "safeName": "body" + }, + "snakeCase": { + "unsafeName": "body", + "safeName": "body" + }, + "screamingSnakeCase": { + "unsafeName": "BODY", + "safeName": "BODY" + }, + "pascalCase": { + "unsafeName": "Body", + "safeName": "Body" + } + } + }, + "requestParameterName": { + "originalName": "request", + "camelCase": { + "unsafeName": "request", + "safeName": "request" + }, + "snakeCase": { + "unsafeName": "request", + "safeName": "request" + }, + "screamingSnakeCase": { + "unsafeName": "REQUEST", + "safeName": "REQUEST" + }, + "pascalCase": { + "unsafeName": "Request", + "safeName": "Request" + } + } + }, + "response": { + "value": { + "type": "response", + "responseBodyType": { + "primitive": "STRING", + "type": "primitive" + } + }, + "type": "json" + }, + "errors": [], + "examples": [], + "docs": "GET request with custom api key" } ] } @@ -285,7 +456,7 @@ "hasEndpointsInTree": true }, "sdkConfig": { - "isAuthMandatory": true, + "isAuthMandatory": false, "hasStreamingEndpoints": false, "hasFileDownloadEndpoints": false, "platformHeaders": { diff --git a/seed/fastapi/auth-environment-variables/resources/service/service/service.py b/seed/fastapi/auth-environment-variables/resources/service/service/service.py index 21d9ad5e27c..ace161edc33 100644 --- a/seed/fastapi/auth-environment-variables/resources/service/service/service.py +++ b/seed/fastapi/auth-environment-variables/resources/service/service/service.py @@ -24,7 +24,14 @@ class AbstractServiceService(AbstractFernService): """ @abc.abstractmethod - def get_with_api_key(self, *, auth: ApiAuth) -> str: + def get_with_api_key(self, *, x_another_header: str, auth: ApiAuth) -> str: + """ + GET request with custom api key + """ + ... + + @abc.abstractmethod + def get_with_header(self, *, x_endpoint_header: str, x_another_header: str) -> str: """ GET request with custom api key """ @@ -38,6 +45,7 @@ def get_with_api_key(self, *, auth: ApiAuth) -> str: @classmethod def _init_fern(cls, router: fastapi.APIRouter) -> None: cls.__init_get_with_api_key(router=router) + cls.__init_get_with_header(router=router) @classmethod def __init_get_with_api_key(cls, router: fastapi.APIRouter) -> None: @@ -46,6 +54,8 @@ def __init_get_with_api_key(cls, router: fastapi.APIRouter) -> None: for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): if index == 0: new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "x_another_header": + new_parameters.append(parameter.replace(default=fastapi.Header(alias="X-Another-Header"))) elif parameter_name == "auth": new_parameters.append(parameter.replace(default=fastapi.Depends(FernAuth))) else: @@ -74,3 +84,41 @@ def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: description=AbstractServiceService.get_with_api_key.__doc__, **get_route_args(cls.get_with_api_key, default_tag="service"), )(wrapper) + + @classmethod + def __init_get_with_header(cls, router: fastapi.APIRouter) -> None: + endpoint_function = inspect.signature(cls.get_with_header) + new_parameters: typing.List[inspect.Parameter] = [] + for index, (parameter_name, parameter) in enumerate(endpoint_function.parameters.items()): + if index == 0: + new_parameters.append(parameter.replace(default=fastapi.Depends(cls))) + elif parameter_name == "x_endpoint_header": + new_parameters.append(parameter.replace(default=fastapi.Header(alias="X-Endpoint-Header"))) + elif parameter_name == "x_another_header": + new_parameters.append(parameter.replace(default=fastapi.Header(alias="X-Another-Header"))) + else: + new_parameters.append(parameter) + setattr(cls.get_with_header, "__signature__", endpoint_function.replace(parameters=new_parameters)) + + @functools.wraps(cls.get_with_header) + def wrapper(*args: typing.Any, **kwargs: typing.Any) -> str: + try: + return cls.get_with_header(*args, **kwargs) + except FernHTTPException as e: + logging.getLogger(f"{cls.__module__}.{cls.__name__}").warn( + f"Endpoint 'get_with_header' unexpectedly threw {e.__class__.__name__}. " + + f"If this was intentional, please add {e.__class__.__name__} to " + + "the endpoint's errors list in your Fern Definition." + ) + raise e + + # this is necessary for FastAPI to find forward-ref'ed type hints. + # https://github.com/tiangolo/fastapi/pull/5077 + wrapper.__globals__.update(cls.get_with_header.__globals__) + + router.get( + path="//apiKeyInHeader", + response_model=str, + description=AbstractServiceService.get_with_header.__doc__, + **get_route_args(cls.get_with_header, default_tag="service"), + )(wrapper) diff --git a/seed/go-fiber/auth-environment-variables/service.go b/seed/go-fiber/auth-environment-variables/service.go new file mode 100644 index 00000000000..0b93ffccf5c --- /dev/null +++ b/seed/go-fiber/auth-environment-variables/service.go @@ -0,0 +1,8 @@ +// This file was auto-generated by Fern from our API Definition. + +package authenvironmentvariables + +type HeaderAuthRequest struct { + // Specifies the endpoint key. + XEndpointHeader string `header:"X-Endpoint-Header"` +} diff --git a/seed/go-model/auth-environment-variables/service.go b/seed/go-model/auth-environment-variables/service.go new file mode 100644 index 00000000000..aab7631e168 --- /dev/null +++ b/seed/go-model/auth-environment-variables/service.go @@ -0,0 +1,3 @@ +// This file was auto-generated by Fern from our API Definition. + +package authenvironmentvariables diff --git a/seed/go-sdk/auth-environment-variables/core/request_option.go b/seed/go-sdk/auth-environment-variables/core/request_option.go index ff9ad16dd7f..46223685851 100644 --- a/seed/go-sdk/auth-environment-variables/core/request_option.go +++ b/seed/go-sdk/auth-environment-variables/core/request_option.go @@ -17,11 +17,12 @@ type RequestOption interface { // This type is primarily used by the generated code and is not meant // to be used directly; use the option package instead. type RequestOptions struct { - BaseURL string - HTTPClient HTTPClient - HTTPHeader http.Header - MaxAttempts uint - ApiKey string + BaseURL string + HTTPClient HTTPClient + HTTPHeader http.Header + MaxAttempts uint + ApiKey string + XAnotherHeader string } // NewRequestOptions returns a new *RequestOptions value. @@ -43,6 +44,7 @@ func NewRequestOptions(opts ...RequestOption) *RequestOptions { func (r *RequestOptions) ToHeader() http.Header { header := r.cloneHeader() header.Set("X-FERN-API-KEY", fmt.Sprintf("%v", r.ApiKey)) + header.Set("X-Another-Header", fmt.Sprintf("%v", r.XAnotherHeader)) return header } @@ -98,3 +100,12 @@ type ApiKeyOption struct { func (a *ApiKeyOption) applyRequestOptions(opts *RequestOptions) { opts.ApiKey = a.ApiKey } + +// XAnotherHeaderOption implements the RequestOption interface. +type XAnotherHeaderOption struct { + XAnotherHeader string +} + +func (x *XAnotherHeaderOption) applyRequestOptions(opts *RequestOptions) { + opts.XAnotherHeader = x.XAnotherHeader +} diff --git a/seed/go-sdk/auth-environment-variables/option/request_option.go b/seed/go-sdk/auth-environment-variables/option/request_option.go index b9e0bd6dbe0..4c4e234713d 100644 --- a/seed/go-sdk/auth-environment-variables/option/request_option.go +++ b/seed/go-sdk/auth-environment-variables/option/request_option.go @@ -46,3 +46,10 @@ func WithApiKey(apiKey string) *core.ApiKeyOption { ApiKey: apiKey, } } + +// WithXAnotherHeader sets the xAnotherHeader request header. +func WithXAnotherHeader(xAnotherHeader string) *core.XAnotherHeaderOption { + return &core.XAnotherHeaderOption{ + XAnotherHeader: xAnotherHeader, + } +} diff --git a/seed/go-sdk/auth-environment-variables/service.go b/seed/go-sdk/auth-environment-variables/service.go new file mode 100644 index 00000000000..79399df39e2 --- /dev/null +++ b/seed/go-sdk/auth-environment-variables/service.go @@ -0,0 +1,8 @@ +// This file was auto-generated by Fern from our API Definition. + +package authenvironmentvariables + +type HeaderAuthRequest struct { + // Specifies the endpoint key. + XEndpointHeader string `json:"-" url:"-"` +} diff --git a/seed/go-sdk/auth-environment-variables/service/client.go b/seed/go-sdk/auth-environment-variables/service/client.go index fc94c56d487..02470c38f99 100644 --- a/seed/go-sdk/auth-environment-variables/service/client.go +++ b/seed/go-sdk/auth-environment-variables/service/client.go @@ -4,6 +4,8 @@ package service import ( context "context" + fmt "fmt" + fern "github.com/auth-environment-variables/fern" core "github.com/auth-environment-variables/fern/core" option "github.com/auth-environment-variables/fern/option" http "net/http" @@ -63,3 +65,40 @@ func (c *Client) GetWithApiKey( } return response, nil } + +// GET request with custom api key +func (c *Client) GetWithHeader( + ctx context.Context, + request *fern.HeaderAuthRequest, + opts ...option.RequestOption, +) (string, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "apiKeyInHeader" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + headers.Add("X-Endpoint-Header", fmt.Sprintf("%v", request.XEndpointHeader)) + + var response string + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + MaxAttempts: options.MaxAttempts, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return "", err + } + return response, nil +} diff --git a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/SeedAuthEnvironmentVariablesClientBuilder.java b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/SeedAuthEnvironmentVariablesClientBuilder.java index d248db006c7..a1b0b1fb478 100644 --- a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/SeedAuthEnvironmentVariablesClientBuilder.java +++ b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/SeedAuthEnvironmentVariablesClientBuilder.java @@ -11,6 +11,8 @@ public final class SeedAuthEnvironmentVariablesClientBuilder { private String apiKey = System.getenv("FERN_API_KEY"); + private String xAnotherHeader = null; + private Environment environment; /** @@ -22,16 +24,22 @@ public SeedAuthEnvironmentVariablesClientBuilder apiKey(String apiKey) { return this; } + /** + * Sets xAnotherHeader + */ + public SeedAuthEnvironmentVariablesClientBuilder xAnotherHeader(String xAnotherHeader) { + this.xAnotherHeader = xAnotherHeader; + return this; + } + public SeedAuthEnvironmentVariablesClientBuilder url(String url) { this.environment = Environment.custom(url); return this; } public SeedAuthEnvironmentVariablesClient build() { - if (apiKey == null) { - throw new RuntimeException("Please provide apiKey or set the FERN_API_KEY environment variable."); - } this.clientOptionsBuilder.addHeader("X-FERN-API-KEY", this.apiKey); + this.clientOptionsBuilder.addHeader("X-Another-Header", this.xAnotherHeader); clientOptionsBuilder.environment(this.environment); return new SeedAuthEnvironmentVariablesClient(clientOptionsBuilder.build()); } diff --git a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/core/RequestOptions.java b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/core/RequestOptions.java index 06772ff6990..10039c096a1 100644 --- a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/core/RequestOptions.java +++ b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/core/RequestOptions.java @@ -11,12 +11,15 @@ public final class RequestOptions { private final String apiKey; + private final String xAnotherHeader; + private final Optional timeout; private final TimeUnit timeoutTimeUnit; - private RequestOptions(String apiKey, Optional timeout, TimeUnit timeoutTimeUnit) { + private RequestOptions(String apiKey, String xAnotherHeader, Optional timeout, TimeUnit timeoutTimeUnit) { this.apiKey = apiKey; + this.xAnotherHeader = xAnotherHeader; this.timeout = timeout; this.timeoutTimeUnit = timeoutTimeUnit; } @@ -34,6 +37,9 @@ public Map getHeaders() { if (this.apiKey != null) { headers.put("X-FERN-API-KEY", this.apiKey); } + if (this.xAnotherHeader != null) { + headers.put("X-Another-Header", this.xAnotherHeader); + } return headers; } @@ -44,6 +50,8 @@ public static Builder builder() { public static final class Builder { private String apiKey = null; + private String xAnotherHeader = null; + private Optional timeout = null; private TimeUnit timeoutTimeUnit = TimeUnit.SECONDS; @@ -53,6 +61,11 @@ public Builder apiKey(String apiKey) { return this; } + public Builder xAnotherHeader(String xAnotherHeader) { + this.xAnotherHeader = xAnotherHeader; + return this; + } + public Builder timeout(Integer timeout) { this.timeout = Optional.of(timeout); return this; @@ -65,7 +78,7 @@ public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { } public RequestOptions build() { - return new RequestOptions(apiKey, timeout, timeoutTimeUnit); + return new RequestOptions(apiKey, xAnotherHeader, timeout, timeoutTimeUnit); } } } diff --git a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/ServiceClient.java b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/ServiceClient.java index 71478368af2..5a98bd13bcd 100644 --- a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/ServiceClient.java +++ b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/ServiceClient.java @@ -7,6 +7,7 @@ import com.seed.authEnvironmentVariables.core.ClientOptions; import com.seed.authEnvironmentVariables.core.ObjectMappers; import com.seed.authEnvironmentVariables.core.RequestOptions; +import com.seed.authEnvironmentVariables.resources.service.requests.HeaderAuthRequest; import java.io.IOException; import okhttp3.Headers; import okhttp3.HttpUrl; @@ -58,4 +59,43 @@ public String getWithApiKey(RequestOptions requestOptions) { throw new RuntimeException(e); } } + + /** + * GET request with custom api key + */ + public String getWithHeader(HeaderAuthRequest request) { + return getWithHeader(request, null); + } + + /** + * GET request with custom api key + */ + public String getWithHeader(HeaderAuthRequest request, RequestOptions requestOptions) { + HttpUrl httpUrl = HttpUrl.parse(this.clientOptions.environment().getUrl()) + .newBuilder() + .addPathSegments("apiKeyInHeader") + .build(); + Request.Builder _requestBuilder = new Request.Builder() + .url(httpUrl) + .method("GET", null) + .headers(Headers.of(clientOptions.headers(requestOptions))) + .addHeader("Content-Type", "application/json"); + _requestBuilder.addHeader("X-Endpoint-Header", request.getXEndpointHeader()); + Request okhttpRequest = _requestBuilder.build(); + try { + OkHttpClient client = clientOptions.httpClient(); + if (requestOptions != null && requestOptions.getTimeout().isPresent()) { + client = clientOptions.httpClientWithTimeout(requestOptions); + } + Response response = client.newCall(okhttpRequest).execute(); + if (response.isSuccessful()) { + return ObjectMappers.JSON_MAPPER.readValue(response.body().string(), String.class); + } + throw new ApiError( + response.code(), + ObjectMappers.JSON_MAPPER.readValue(response.body().string(), Object.class)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/requests/HeaderAuthRequest.java b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/requests/HeaderAuthRequest.java new file mode 100644 index 00000000000..b8d5a8a7f31 --- /dev/null +++ b/seed/java-sdk/auth-environment-variables/src/main/java/com/seed/authEnvironmentVariables/resources/service/requests/HeaderAuthRequest.java @@ -0,0 +1,108 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.authEnvironmentVariables.resources.service.requests; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.seed.authEnvironmentVariables.core.ObjectMappers; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonDeserialize(builder = HeaderAuthRequest.Builder.class) +public final class HeaderAuthRequest { + private final String xEndpointHeader; + + private final Map additionalProperties; + + private HeaderAuthRequest(String xEndpointHeader, Map additionalProperties) { + this.xEndpointHeader = xEndpointHeader; + this.additionalProperties = additionalProperties; + } + + /** + * @return Specifies the endpoint key. + */ + @JsonProperty("X-Endpoint-Header") + public String getXEndpointHeader() { + return xEndpointHeader; + } + + @java.lang.Override + public boolean equals(Object other) { + if (this == other) return true; + return other instanceof HeaderAuthRequest && equalTo((HeaderAuthRequest) other); + } + + @JsonAnyGetter + public Map getAdditionalProperties() { + return this.additionalProperties; + } + + private boolean equalTo(HeaderAuthRequest other) { + return xEndpointHeader.equals(other.xEndpointHeader); + } + + @java.lang.Override + public int hashCode() { + return Objects.hash(this.xEndpointHeader); + } + + @java.lang.Override + public String toString() { + return ObjectMappers.stringify(this); + } + + public static XEndpointHeaderStage builder() { + return new Builder(); + } + + public interface XEndpointHeaderStage { + _FinalStage xEndpointHeader(String xEndpointHeader); + + Builder from(HeaderAuthRequest other); + } + + public interface _FinalStage { + HeaderAuthRequest build(); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static final class Builder implements XEndpointHeaderStage, _FinalStage { + private String xEndpointHeader; + + @JsonAnySetter + private Map additionalProperties = new HashMap<>(); + + private Builder() {} + + @java.lang.Override + public Builder from(HeaderAuthRequest other) { + xEndpointHeader(other.getXEndpointHeader()); + return this; + } + + /** + *

Specifies the endpoint key.

+ * @return Reference to {@code this} so that method calls can be chained together. + */ + @java.lang.Override + @JsonSetter("X-Endpoint-Header") + public _FinalStage xEndpointHeader(String xEndpointHeader) { + this.xEndpointHeader = xEndpointHeader; + return this; + } + + @java.lang.Override + public HeaderAuthRequest build() { + return new HeaderAuthRequest(xEndpointHeader, additionalProperties); + } + } +} diff --git a/seed/java-spring/auth-environment-variables/resources/service/ServiceService.java b/seed/java-spring/auth-environment-variables/resources/service/ServiceService.java index 9d1f0f58bf3..7e1d08be41f 100644 --- a/seed/java-spring/auth-environment-variables/resources/service/ServiceService.java +++ b/seed/java-spring/auth-environment-variables/resources/service/ServiceService.java @@ -19,5 +19,13 @@ public interface ServiceService { value = "/apiKey", produces = "application/json" ) - String getWithApiKey(@RequestHeader("X-FERN-API-KEY") ApiKey auth, Principal principal); + String getWithApiKey(@RequestHeader("X-FERN-API-KEY") ApiKey auth, Principal principal, + @RequestHeader("X-Another-Header") String xAnotherHeader); + + @GetMapping( + value = "/apiKeyInHeader", + produces = "application/json" + ) + String getWithHeader(@RequestHeader("X-Another-Header") String xAnotherHeader, + @RequestHeader("X-Endpoint-Header") String xEndpointHeader); } diff --git a/seed/openapi/auth-environment-variables/openapi.yml b/seed/openapi/auth-environment-variables/openapi.yml index 48e10973a65..bc925f405c1 100644 --- a/seed/openapi/auth-environment-variables/openapi.yml +++ b/seed/openapi/auth-environment-variables/openapi.yml @@ -19,6 +19,26 @@ paths: type: string security: - ApiKeyAuth: [] + /apiKeyInHeader: + get: + description: GET request with custom api key + operationId: service_getWithHeader + tags: + - Service + parameters: + - name: X-Endpoint-Header + in: header + description: Specifies the endpoint key. + required: true + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + type: string components: schemas: {} securitySchemes: diff --git a/seed/postman/auth-environment-variables/collection.json b/seed/postman/auth-environment-variables/collection.json index b3c670e8419..c73fb18388b 100644 --- a/seed/postman/auth-environment-variables/collection.json +++ b/seed/postman/auth-environment-variables/collection.json @@ -71,6 +71,42 @@ "body": null }, "response": [] + }, + { + "_type": "endpoint", + "name": "Get With Header", + "request": { + "description": "GET request with custom api key", + "url": { + "raw": "{{baseUrl}}/apiKeyInHeader", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "apiKeyInHeader" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "X-FERN-API-KEY", + "value": "{{apiKey}}", + "type": "string", + "description": null + }, + { + "key": "X-Endpoint-Header", + "description": "Specifies the endpoint key.", + "type": "text", + "value": "\"example\"" + } + ], + "method": "GET", + "auth": null, + "body": null + }, + "response": [] } ] } diff --git a/seed/python-sdk/auth-environment-variables/src/seed/client.py b/seed/python-sdk/auth-environment-variables/src/seed/client.py index 60a98c88e34..8faa9432265 100644 --- a/seed/python-sdk/auth-environment-variables/src/seed/client.py +++ b/seed/python-sdk/auth-environment-variables/src/seed/client.py @@ -17,6 +17,8 @@ class SeedAuthEnvironmentVariables: Parameters: - base_url: str. The base url to use for requests from the client. + - x_another_header: typing.Optional[str]. + - api_key: typing.Optional[str]. - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. @@ -26,6 +28,7 @@ class SeedAuthEnvironmentVariables: from seed.client import SeedAuthEnvironmentVariables client = SeedAuthEnvironmentVariables( + x_another_header="YOUR_X_ANOTHER_HEADER", api_key="YOUR_API_KEY", base_url="https://yourhost.com/path/to/api", ) @@ -35,14 +38,20 @@ def __init__( self, *, base_url: str, + x_another_header: typing.Optional[str] = os.getenv("ANOTHER_ENV_VAR"), api_key: typing.Optional[str] = os.getenv("FERN_API_KEY"), timeout: typing.Optional[float] = 60, httpx_client: typing.Optional[httpx.Client] = None ): + if x_another_header is None: + raise ApiError( + body="The client must be instantiated be either passing in x_another_header or setting ANOTHER_ENV_VAR" + ) if api_key is None: raise ApiError(body="The client must be instantiated be either passing in api_key or setting FERN_API_KEY") self._client_wrapper = SyncClientWrapper( base_url=base_url, + x_another_header=x_another_header, api_key=api_key, httpx_client=httpx.Client(timeout=timeout) if httpx_client is None else httpx_client, ) @@ -56,6 +65,8 @@ class AsyncSeedAuthEnvironmentVariables: Parameters: - base_url: str. The base url to use for requests from the client. + - x_another_header: typing.Optional[str]. + - api_key: typing.Optional[str]. - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. @@ -65,6 +76,7 @@ class AsyncSeedAuthEnvironmentVariables: from seed.client import AsyncSeedAuthEnvironmentVariables client = AsyncSeedAuthEnvironmentVariables( + x_another_header="YOUR_X_ANOTHER_HEADER", api_key="YOUR_API_KEY", base_url="https://yourhost.com/path/to/api", ) @@ -74,14 +86,20 @@ def __init__( self, *, base_url: str, + x_another_header: typing.Optional[str] = os.getenv("ANOTHER_ENV_VAR"), api_key: typing.Optional[str] = os.getenv("FERN_API_KEY"), timeout: typing.Optional[float] = 60, httpx_client: typing.Optional[httpx.AsyncClient] = None ): + if x_another_header is None: + raise ApiError( + body="The client must be instantiated be either passing in x_another_header or setting ANOTHER_ENV_VAR" + ) if api_key is None: raise ApiError(body="The client must be instantiated be either passing in api_key or setting FERN_API_KEY") self._client_wrapper = AsyncClientWrapper( base_url=base_url, + x_another_header=x_another_header, api_key=api_key, httpx_client=httpx.AsyncClient(timeout=timeout) if httpx_client is None else httpx_client, ) diff --git a/seed/python-sdk/auth-environment-variables/src/seed/core/client_wrapper.py b/seed/python-sdk/auth-environment-variables/src/seed/core/client_wrapper.py index c8c83be851e..6c3adc5ca4c 100644 --- a/seed/python-sdk/auth-environment-variables/src/seed/core/client_wrapper.py +++ b/seed/python-sdk/auth-environment-variables/src/seed/core/client_wrapper.py @@ -6,7 +6,8 @@ class BaseClientWrapper: - def __init__(self, *, api_key: str, base_url: str): + def __init__(self, *, x_another_header: str, api_key: str, base_url: str): + self._x_another_header = x_another_header self.api_key = api_key self._base_url = base_url @@ -16,6 +17,7 @@ def get_headers(self) -> typing.Dict[str, str]: "X-Fern-SDK-Name": "seed", "X-Fern-SDK-Version": "0.0.0", } + headers["X-Another-Header"] = self._x_another_header headers["X-FERN-API-KEY"] = self.api_key return headers @@ -24,12 +26,12 @@ def get_base_url(self) -> str: class SyncClientWrapper(BaseClientWrapper): - def __init__(self, *, api_key: str, base_url: str, httpx_client: httpx.Client): - super().__init__(api_key=api_key, base_url=base_url) + def __init__(self, *, x_another_header: str, api_key: str, base_url: str, httpx_client: httpx.Client): + super().__init__(x_another_header=x_another_header, api_key=api_key, base_url=base_url) self.httpx_client = httpx_client class AsyncClientWrapper(BaseClientWrapper): - def __init__(self, *, api_key: str, base_url: str, httpx_client: httpx.AsyncClient): - super().__init__(api_key=api_key, base_url=base_url) + def __init__(self, *, x_another_header: str, api_key: str, base_url: str, httpx_client: httpx.AsyncClient): + super().__init__(x_another_header=x_another_header, api_key=api_key, base_url=base_url) self.httpx_client = httpx_client diff --git a/seed/python-sdk/auth-environment-variables/src/seed/resources/service/client.py b/seed/python-sdk/auth-environment-variables/src/seed/resources/service/client.py index 71f1626b571..a90c8a20088 100644 --- a/seed/python-sdk/auth-environment-variables/src/seed/resources/service/client.py +++ b/seed/python-sdk/auth-environment-variables/src/seed/resources/service/client.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +import os import typing import urllib.parse from json.decoder import JSONDecodeError @@ -53,6 +54,47 @@ def get_with_api_key(self, *, request_options: typing.Optional[RequestOptions] = raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def get_with_header( + self, + *, + x_endpoint_header: typing.Optional[str] = os.getenv("MY_HEADER_ENV"), + request_options: typing.Optional[RequestOptions] = None, + ) -> str: + """ + GET request with custom api key + + Parameters: + - x_endpoint_header: typing.Optional[str]. Specifies the endpoint key. + + - request_options: typing.Optional[RequestOptions]. Request-specific configuration. + """ + _response = self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "apiKeyInHeader"), + params=jsonable_encoder( + request_options.get("additional_query_parameters") if request_options is not None else None + ), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self._client_wrapper.get_headers(), + "X-Endpoint-Header": x_endpoint_header, + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + timeout=request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else 60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(str, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + class AsyncServiceClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -90,3 +132,44 @@ async def get_with_api_key(self, *, request_options: typing.Optional[RequestOpti except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_with_header( + self, + *, + x_endpoint_header: typing.Optional[str] = os.getenv("MY_HEADER_ENV"), + request_options: typing.Optional[RequestOptions] = None, + ) -> str: + """ + GET request with custom api key + + Parameters: + - x_endpoint_header: typing.Optional[str]. Specifies the endpoint key. + + - request_options: typing.Optional[RequestOptions]. Request-specific configuration. + """ + _response = await self._client_wrapper.httpx_client.request( + "GET", + urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "apiKeyInHeader"), + params=jsonable_encoder( + request_options.get("additional_query_parameters") if request_options is not None else None + ), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self._client_wrapper.get_headers(), + "X-Endpoint-Header": x_endpoint_header, + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + timeout=request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else 60, + ) + if 200 <= _response.status_code < 300: + return pydantic.parse_obj_as(str, _response.json()) # type: ignore + try: + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/seed/python-sdk/seed.yml b/seed/python-sdk/seed.yml index 5760018f362..833178f8aa6 100644 --- a/seed/python-sdk/seed.yml +++ b/seed/python-sdk/seed.yml @@ -1,4 +1,4 @@ -irVersion: v34 +irVersion: v36 docker: fernapi/fern-python-sdk:latest dockerCommand: docker build -f ./generators/python/sdk/Dockerfile -t fernapi/fern-python-sdk:latest ./generators/python language: python diff --git a/seed/python-sdk/websocket/src/seed/client.py b/seed/python-sdk/websocket/src/seed/client.py index ca46e7b6232..137e2a80ebd 100644 --- a/seed/python-sdk/websocket/src/seed/client.py +++ b/seed/python-sdk/websocket/src/seed/client.py @@ -8,6 +8,23 @@ class SeedWebsocket: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions. + + Parameters: + - base_url: str. The base url to use for requests from the client. + + - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. + + - httpx_client: typing.Optional[httpx.Client]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + --- + from seed.client import SeedWebsocket + + client = SeedWebsocket( + base_url="https://yourhost.com/path/to/api", + ) + """ + def __init__( self, *, base_url: str, timeout: typing.Optional[float] = 60, httpx_client: typing.Optional[httpx.Client] = None ): @@ -17,6 +34,23 @@ def __init__( class AsyncSeedWebsocket: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions. + + Parameters: + - base_url: str. The base url to use for requests from the client. + + - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. + + - httpx_client: typing.Optional[httpx.AsyncClient]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + --- + from seed.client import AsyncSeedWebsocket + + client = AsyncSeedWebsocket( + base_url="https://yourhost.com/path/to/api", + ) + """ + def __init__( self, *, diff --git a/seed/python-sdk/websocket/src/seed/core/__init__.py b/seed/python-sdk/websocket/src/seed/core/__init__.py index e42d263c2b6..4c53b36cabd 100644 --- a/seed/python-sdk/websocket/src/seed/core/__init__.py +++ b/seed/python-sdk/websocket/src/seed/core/__init__.py @@ -3,6 +3,7 @@ from .api_error import ApiError from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper from .datetime_utils import serialize_datetime +from .file import File, convert_file_dict_to_httpx_tuples from .jsonable_encoder import jsonable_encoder from .remove_none_from_dict import remove_none_from_dict from .request_options import RequestOptions @@ -11,8 +12,10 @@ "ApiError", "AsyncClientWrapper", "BaseClientWrapper", + "File", "RequestOptions", "SyncClientWrapper", + "convert_file_dict_to_httpx_tuples", "jsonable_encoder", "remove_none_from_dict", "serialize_datetime", diff --git a/seed/ruby-sdk/auth-environment-variables/lib/requests.rb b/seed/ruby-sdk/auth-environment-variables/lib/requests.rb index a95bfbfa547..8ef407a79fb 100644 --- a/seed/ruby-sdk/auth-environment-variables/lib/requests.rb +++ b/seed/ruby-sdk/auth-environment-variables/lib/requests.rb @@ -11,14 +11,16 @@ class RequestClient # @param max_retries [Long] The number of times to retry a failed request, defaults to 2. # @param timeout_in_seconds [Long] # @param api_key [String] + # @param x_another_header [String] # @return [RequestClient] - def initialize(api_key:, max_retries: nil, timeout_in_seconds: nil) + def initialize(api_key:, x_another_header:, max_retries: nil, timeout_in_seconds: nil) @headers = { "X-Fern-Language": "Ruby", "X-Fern-SDK-Name": "SeedAuthEnvironmentVariablesClient", "X-Fern-SDK-Version": "0.0.1", "X-FERN-API-KEY": (api_key || ENV["FERN_API_KEY"]).to_s } + @headers["X-Another-Header"] = x_another_header unless x_another_header.nil? @conn = Faraday.new(headers: @headers) do |faraday| faraday.request :json faraday.response :raise_error, include_request: true @@ -34,14 +36,16 @@ class AsyncRequestClient # @param max_retries [Long] The number of times to retry a failed request, defaults to 2. # @param timeout_in_seconds [Long] # @param api_key [String] + # @param x_another_header [String] # @return [AsyncRequestClient] - def initialize(api_key:, max_retries: nil, timeout_in_seconds: nil) + def initialize(api_key:, x_another_header:, max_retries: nil, timeout_in_seconds: nil) @headers = { "X-Fern-Language": "Ruby", "X-Fern-SDK-Name": "SeedAuthEnvironmentVariablesClient", "X-Fern-SDK-Version": "0.0.1", "X-FERN-API-KEY": (api_key || ENV["FERN_API_KEY"]).to_s } + @headers["X-Another-Header"] = x_another_header unless x_another_header.nil? @conn = Faraday.new(headers: @headers) do |faraday| faraday.request :json faraday.response :raise_error, include_request: true @@ -54,19 +58,22 @@ def initialize(api_key:, max_retries: nil, timeout_in_seconds: nil) # Additional options for request-specific configuration when calling APIs via the SDK. class RequestOptions - attr_reader :api_key, :additional_headers, :additional_query_parameters, :additional_body_parameters, - :timeout_in_seconds + attr_reader :api_key, :x_another_header, :additional_headers, :additional_query_parameters, + :additional_body_parameters, :timeout_in_seconds # @param api_key [String] + # @param x_another_header [String] # @param additional_headers [Hash{String => Object}] # @param additional_query_parameters [Hash{String => Object}] # @param additional_body_parameters [Hash{String => Object}] # @param timeout_in_seconds [Long] # @return [RequestOptions] - def initialize(api_key: nil, additional_headers: nil, additional_query_parameters: nil, + def initialize(api_key: nil, x_another_header: nil, additional_headers: nil, additional_query_parameters: nil, additional_body_parameters: nil, timeout_in_seconds: nil) # @type [String] @api_key = api_key + # @type [String] + @x_another_header = x_another_header # @type [Hash{String => Object}] @additional_headers = additional_headers # @type [Hash{String => Object}] @@ -80,19 +87,22 @@ def initialize(api_key: nil, additional_headers: nil, additional_query_parameter # Additional options for request-specific configuration when calling APIs via the SDK. class IdempotencyRequestOptions - attr_reader :api_key, :additional_headers, :additional_query_parameters, :additional_body_parameters, - :timeout_in_seconds + attr_reader :api_key, :x_another_header, :additional_headers, :additional_query_parameters, + :additional_body_parameters, :timeout_in_seconds # @param api_key [String] + # @param x_another_header [String] # @param additional_headers [Hash{String => Object}] # @param additional_query_parameters [Hash{String => Object}] # @param additional_body_parameters [Hash{String => Object}] # @param timeout_in_seconds [Long] # @return [IdempotencyRequestOptions] - def initialize(api_key: nil, additional_headers: nil, additional_query_parameters: nil, + def initialize(api_key: nil, x_another_header: nil, additional_headers: nil, additional_query_parameters: nil, additional_body_parameters: nil, timeout_in_seconds: nil) # @type [String] @api_key = api_key + # @type [String] + @x_another_header = x_another_header # @type [Hash{String => Object}] @additional_headers = additional_headers # @type [Hash{String => Object}] diff --git a/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client.rb b/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client.rb index 55c9190ae19..0516f8b933d 100644 --- a/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client.rb +++ b/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client.rb @@ -11,10 +11,11 @@ class Client # @param max_retries [Long] The number of times to retry a failed request, defaults to 2. # @param timeout_in_seconds [Long] # @param api_key [String] + # @param x_another_header [String] # @return [Client] - def initialize(api_key:, max_retries: nil, timeout_in_seconds: nil) + def initialize(api_key:, x_another_header:, max_retries: nil, timeout_in_seconds: nil) @request_client = RequestClient.new(max_retries: max_retries, timeout_in_seconds: timeout_in_seconds, - api_key: api_key) + api_key: api_key, x_another_header: x_another_header) @service = ServiceClient.new(request_client: @request_client) end end @@ -25,10 +26,11 @@ class AsyncClient # @param max_retries [Long] The number of times to retry a failed request, defaults to 2. # @param timeout_in_seconds [Long] # @param api_key [String] + # @param x_another_header [String] # @return [AsyncClient] - def initialize(api_key:, max_retries: nil, timeout_in_seconds: nil) + def initialize(api_key:, x_another_header:, max_retries: nil, timeout_in_seconds: nil) @async_request_client = AsyncRequestClient.new(max_retries: max_retries, timeout_in_seconds: timeout_in_seconds, - api_key: api_key) + api_key: api_key, x_another_header: x_another_header) @service = AsyncServiceClient.new(request_client: @async_request_client) end end diff --git a/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client/service/client.rb b/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client/service/client.rb index 2850db7b2d3..a0967172aa6 100644 --- a/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client/service/client.rb +++ b/seed/ruby-sdk/auth-environment-variables/lib/seed_auth_environment_variables_client/service/client.rb @@ -22,10 +22,30 @@ def get_with_api_key(request_options: nil) response = @request_client.conn.get("/apiKey") do |req| req.options.timeout = request_options.timeout_in_seconds unless request_options&.timeout_in_seconds.nil? req.headers["X-FERN-API-KEY"] = request_options.api_key unless request_options&.api_key.nil? + req.headers["X-Another-Header"] = request_options.x_another_header unless request_options&.x_another_header.nil? req.headers = { **req.headers, **(request_options&.additional_headers || {}) }.compact end response.body end + + # GET request with custom api key + # + # @param x_endpoint_header [String] Specifies the endpoint key. + # @param request_options [RequestOptions] + # @return [String] + def get_with_header(x_endpoint_header:, request_options: nil) + response = @request_client.conn.get("/apiKeyInHeader") do |req| + req.options.timeout = request_options.timeout_in_seconds unless request_options&.timeout_in_seconds.nil? + req.headers["X-FERN-API-KEY"] = request_options.api_key unless request_options&.api_key.nil? + req.headers["X-Another-Header"] = request_options.x_another_header unless request_options&.x_another_header.nil? + req.headers = { + **req.headers, + **(request_options&.additional_headers || {}), + "X-Endpoint-Header": x_endpoint_header + }.compact + end + response.body + end end class AsyncServiceClient @@ -47,10 +67,38 @@ def get_with_api_key(request_options: nil) response = @request_client.conn.get("/apiKey") do |req| req.options.timeout = request_options.timeout_in_seconds unless request_options&.timeout_in_seconds.nil? req.headers["X-FERN-API-KEY"] = request_options.api_key unless request_options&.api_key.nil? + unless request_options&.x_another_header.nil? + req.headers["X-Another-Header"] = + request_options.x_another_header + end req.headers = { **req.headers, **(request_options&.additional_headers || {}) }.compact end response.body end end + + # GET request with custom api key + # + # @param x_endpoint_header [String] Specifies the endpoint key. + # @param request_options [RequestOptions] + # @return [String] + def get_with_header(x_endpoint_header:, request_options: nil) + Async do + response = @request_client.conn.get("/apiKeyInHeader") do |req| + req.options.timeout = request_options.timeout_in_seconds unless request_options&.timeout_in_seconds.nil? + req.headers["X-FERN-API-KEY"] = request_options.api_key unless request_options&.api_key.nil? + unless request_options&.x_another_header.nil? + req.headers["X-Another-Header"] = + request_options.x_another_header + end + req.headers = { + **req.headers, + **(request_options&.additional_headers || {}), + "X-Endpoint-Header": x_endpoint_header + }.compact + end + response.body + end + end end end diff --git a/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.d.ts b/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.d.ts index 281d4831f0f..231bc6e7a5e 100644 --- a/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.d.ts +++ b/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.d.ts @@ -8,6 +8,11 @@ export interface ServiceServiceMethods { cookie: (cookie: string, value: string, options?: express.CookieOptions) => void; locals: any; }): void | Promise; + getWithHeader(req: express.Request, res: { + send: (responseBody: string) => Promise; + cookie: (cookie: string, value: string, options?: express.CookieOptions) => void; + locals: any; + }): void | Promise; } export declare class ServiceService { private readonly methods; diff --git a/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.js b/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.js index 049e8c3a8fe..aec4cff32b6 100644 --- a/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.js +++ b/seed/ts-express/auth-environment-variables/api/resources/service/service/ServiceService.js @@ -81,6 +81,33 @@ class ServiceService { next(error); } })); + this.router.get("/apiKeyInHeader", (req, res, next) => __awaiter(this, void 0, void 0, function* () { + try { + yield this.methods.getWithHeader(req, { + send: (responseBody) => __awaiter(this, void 0, void 0, function* () { + res.json(yield serializers.service.getWithHeader.Response.jsonOrThrow(responseBody, { + unrecognizedObjectKeys: "strip", + })); + }), + cookie: res.cookie.bind(res), + locals: res.locals, + }); + next(); + } + catch (error) { + console.error(error); + if (error instanceof errors.SeedAuthEnvironmentVariablesError) { + console.warn(`Endpoint 'getWithHeader' unexpectedly threw ${error.constructor.name}.` + + ` If this was intentional, please add ${error.constructor.name} to` + + " the endpoint's errors list in your Fern Definition."); + yield error.send(res); + } + else { + res.status(500).json("Internal Server Error"); + } + next(error); + } + })); return this.router; } } diff --git a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.d.ts b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.d.ts new file mode 100644 index 00000000000..37ff6d43253 --- /dev/null +++ b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.d.ts @@ -0,0 +1,9 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +import * as serializers from "../../.."; +import * as core from "../../../../core"; +export declare const Response: core.serialization.Schema; +export declare namespace Response { + type Raw = string; +} diff --git a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.js b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.js new file mode 100644 index 00000000000..2e89916abc1 --- /dev/null +++ b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/getWithHeader.js @@ -0,0 +1,31 @@ +"use strict"; +/** + * This file was auto-generated by Fern from our API Definition. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Response = void 0; +const core = __importStar(require("../../../../core")); +exports.Response = core.serialization.string(); diff --git a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.d.ts b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.d.ts index 7c29b3134a0..3c61ad467bf 100644 --- a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.d.ts +++ b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.d.ts @@ -1 +1,2 @@ export * as getWithApiKey from "./getWithApiKey"; +export * as getWithHeader from "./getWithHeader"; diff --git a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.js b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.js index 47689be5f4f..f98de8facd2 100644 --- a/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.js +++ b/seed/ts-express/auth-environment-variables/serialization/resources/service/service/index.js @@ -23,5 +23,6 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getWithApiKey = void 0; +exports.getWithHeader = exports.getWithApiKey = void 0; exports.getWithApiKey = __importStar(require("./getWithApiKey")); +exports.getWithHeader = __importStar(require("./getWithHeader")); diff --git a/seed/ts-sdk/auth-environment-variables/src/Client.ts b/seed/ts-sdk/auth-environment-variables/src/Client.ts index 497c4ed5f20..f7fd08aeb66 100644 --- a/seed/ts-sdk/auth-environment-variables/src/Client.ts +++ b/seed/ts-sdk/auth-environment-variables/src/Client.ts @@ -8,7 +8,8 @@ import { Service } from "./api/resources/service/client/Client"; export declare namespace SeedAuthEnvironmentVariablesClient { interface Options { environment: core.Supplier; - apiKey: core.Supplier; + apiKey?: core.Supplier; + xAnotherHeader: core.Supplier; } interface RequestOptions { diff --git a/seed/ts-sdk/auth-environment-variables/src/api/resources/index.ts b/seed/ts-sdk/auth-environment-variables/src/api/resources/index.ts index 22844191e7c..d26478fb1ba 100644 --- a/seed/ts-sdk/auth-environment-variables/src/api/resources/index.ts +++ b/seed/ts-sdk/auth-environment-variables/src/api/resources/index.ts @@ -1 +1,2 @@ export * as service from "./service"; +export * from "./service/client/requests"; diff --git a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/Client.ts b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/Client.ts index 95d8b158e40..7b5741c32e7 100644 --- a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/Client.ts +++ b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/Client.ts @@ -6,11 +6,13 @@ import * as core from "../../../../core"; import urlJoin from "url-join"; import * as serializers from "../../../../serialization"; import * as errors from "../../../../errors"; +import * as SeedAuthEnvironmentVariables from "../../.."; export declare namespace Service { interface Options { environment: core.Supplier; - apiKey: core.Supplier; + apiKey?: core.Supplier; + xAnotherHeader: core.Supplier; } interface RequestOptions { @@ -30,6 +32,7 @@ export class Service { url: urlJoin(await core.Supplier.get(this._options.environment), "apiKey"), method: "GET", headers: { + "X-Another-Header": await core.Supplier.get(this._options.xAnotherHeader), "X-FERN-API-KEY": await core.Supplier.get(this._options.apiKey), "X-Fern-Language": "JavaScript", "X-Fern-SDK-Name": "", @@ -71,4 +74,60 @@ export class Service { }); } } + + /** + * GET request with custom api key + */ + public async getWithHeader( + request: SeedAuthEnvironmentVariables.HeaderAuthRequest, + requestOptions?: Service.RequestOptions + ): Promise { + const { xEndpointHeader } = request; + const _response = await core.fetcher({ + url: urlJoin(await core.Supplier.get(this._options.environment), "apiKeyInHeader"), + method: "GET", + headers: { + "X-Another-Header": await core.Supplier.get(this._options.xAnotherHeader), + "X-FERN-API-KEY": await core.Supplier.get(this._options.apiKey), + "X-Fern-Language": "JavaScript", + "X-Fern-SDK-Name": "", + "X-Fern-SDK-Version": "0.0.1", + "X-Fern-Runtime": core.RUNTIME.type, + "X-Fern-Runtime-Version": core.RUNTIME.version, + "X-Endpoint-Header": xEndpointHeader, + }, + contentType: "application/json", + timeoutMs: requestOptions?.timeoutInSeconds != null ? requestOptions.timeoutInSeconds * 1000 : 60000, + maxRetries: requestOptions?.maxRetries, + }); + if (_response.ok) { + return await serializers.service.getWithHeader.Response.parseOrThrow(_response.body, { + unrecognizedObjectKeys: "passthrough", + allowUnrecognizedUnionMembers: true, + allowUnrecognizedEnumValues: true, + breadcrumbsPrefix: ["response"], + }); + } + + if (_response.error.reason === "status-code") { + throw new errors.SeedAuthEnvironmentVariablesError({ + statusCode: _response.error.statusCode, + body: _response.error.body, + }); + } + + switch (_response.error.reason) { + case "non-json": + throw new errors.SeedAuthEnvironmentVariablesError({ + statusCode: _response.error.statusCode, + body: _response.error.rawBody, + }); + case "timeout": + throw new errors.SeedAuthEnvironmentVariablesTimeoutError(); + case "unknown": + throw new errors.SeedAuthEnvironmentVariablesError({ + message: _response.error.errorMessage, + }); + } + } } diff --git a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/index.ts b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/index.ts index cb0ff5c3b54..415726b7fea 100644 --- a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/index.ts +++ b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/index.ts @@ -1 +1 @@ -export {}; +export * from "./requests"; diff --git a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/HeaderAuthRequest.ts b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/HeaderAuthRequest.ts new file mode 100644 index 00000000000..43232a15065 --- /dev/null +++ b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/HeaderAuthRequest.ts @@ -0,0 +1,10 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +export interface HeaderAuthRequest { + /** + * Specifies the endpoint key. + */ + xEndpointHeader: string; +} diff --git a/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/index.ts b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/index.ts new file mode 100644 index 00000000000..69ad76a7dbc --- /dev/null +++ b/seed/ts-sdk/auth-environment-variables/src/api/resources/service/client/requests/index.ts @@ -0,0 +1 @@ +export { HeaderAuthRequest } from "./HeaderAuthRequest"; diff --git a/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/getWithHeader.ts b/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/getWithHeader.ts new file mode 100644 index 00000000000..287e0e2ae91 --- /dev/null +++ b/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/getWithHeader.ts @@ -0,0 +1,13 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ + +import * as serializers from "../../.."; +import * as core from "../../../../core"; + +export const Response: core.serialization.Schema = + core.serialization.string(); + +export declare namespace Response { + type Raw = string; +} diff --git a/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/index.ts b/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/index.ts index 7c29b3134a0..3c61ad467bf 100644 --- a/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/index.ts +++ b/seed/ts-sdk/auth-environment-variables/src/serialization/resources/service/client/index.ts @@ -1 +1,2 @@ export * as getWithApiKey from "./getWithApiKey"; +export * as getWithHeader from "./getWithHeader"; diff --git a/test-definitions/fern/apis/auth-environment-variables/definition/api.yml b/test-definitions/fern/apis/auth-environment-variables/definition/api.yml index 42913648b93..2c6038ea261 100644 --- a/test-definitions/fern/apis/auth-environment-variables/definition/api.yml +++ b/test-definitions/fern/apis/auth-environment-variables/definition/api.yml @@ -5,3 +5,7 @@ auth-schemes: header: X-FERN-API-KEY type: string env: FERN_API_KEY +headers: + X-Another-Header: + type: string + env: ANOTHER_ENV_VAR diff --git a/test-definitions/fern/apis/auth-environment-variables/definition/service.yml b/test-definitions/fern/apis/auth-environment-variables/definition/service.yml index 479d7a69a99..9e5d595f4a2 100644 --- a/test-definitions/fern/apis/auth-environment-variables/definition/service.yml +++ b/test-definitions/fern/apis/auth-environment-variables/definition/service.yml @@ -10,3 +10,16 @@ service: path: /apiKey method: GET response: string + + getWithHeader: + docs: GET request with custom api key + path: /apiKeyInHeader + method: GET + request: + name: HeaderAuthRequest + headers: + X-Endpoint-Header: + docs: "Specifies the endpoint key." + type: string + env: MY_HEADER_ENV + response: string