Skip to main content

Hooks

Hooks are a way to add custom code to your SDK or Terraform provider to hook into the API invocation lifecycle. This document will guide you through extending the liblab generated SDK with your custom logic using our Hooks framework.

Supported SDK languages and versions:

TypeScriptJavaPythonC#GoTerraformPHP

What are Hooks?

In some use cases, you need to extend the SDK created by liblab, and add your own custom code into the SDK at the generation process. Examples of such use cases include custom authentication or auditing requirements, or providing Terraform plan modifiers.

liblab can extend your SDKs in each of the languages generated, using our Hooks framework. The SDK hooks framework lets you hook in your code into three events in the API invocation lifecycle:

  • Before Request: Code implemented in this section will run before the request. You can use the request object and update the request itself before it goes out to your API.
  • After Response: Code implemented in this section will run after the call returns from your API. You can use the request objects to get context for the API call made and the response object for the response provided.
  • On Error: Code implemented in this section will run in case of an API call error. You can use the request objects to get context for the API call and the exception object for information about the error that accrued.

Happy path

The hook flow for a successful call. SDK is called, request is prepared, the before request hook is called, the request is sent, the response is received, the after response hook is called, and the sdk call returns The hook flow for a successful call. SDK is called, request is prepared, the before request hook is called, the request is sent, the response is received, the after response hook is called, and the sdk call returns

Error path

The hook flow for an unsuccessful call. SDK is called, request is prepared, the before request hook is called, the request is sent, an error is received, the on error hook is called, and the sdk raises an exception The hook flow for an unsuccessful call. SDK is called, request is prepared, the before request hook is called, the request is sent, an error is received, the on error hook is called, and the sdk raises an exception"

Hooks with Terraform

For Terraform you can hook into the terraform plan command to modify the plan before it is applied. You can read more on this in our Terraform provider hooks and custom plan modifiers documentation.

When working with hooks, you can implement only the ones your code needs, before request, after response, or on error. The following code block provides examples for each hook across all supported programming languages.

custom-hook.ts
export class CustomHook implements Hook {
public async beforeRequest(request: HttpRequest, params: Map<string, string>): Promise<HttpRequest> {
// Your code goes here
}

public async afterResponse(request: HttpRequest, response: HttpResponse<any>, params: Map<string, string>): Promise<HttpResponse<any>> {
// Your code goes here
}

public async onError(request: HttpRequest, response: HttpResponse<any>, params: Map<string, string>): Promise<HttpError> {
// Your code goes here
}
}
note

When generating both a Terraform provider and a standalone Go SDK, the hooks are not shared between the Go SDK created for the Terraform provider and the standalone Go SDK.

Add hooks to your liblab project

To add the hooks framework, run the following command:

liblab hooks add

This generates a hooks folder that you can modify to extend the SDK. To ensure it's included in the SDK, the hooks folder must be located in the same directory as your liblab configuration file. Inside the hooks folder, you'll find subfolders for each language specified in your configuration file:

.
├── hooks
│ ├── go
│ ├── csharp
│ ├── java
│ ├── python
│ ├── terraform
│ ├── php
│ └── typescript
├── customPlanModifiers // hooks that are triggered on the `terraform plan` command
│ ├── attributes
│ └── resources
└── liblab.config.json

Each folder contains a complete code project where you can add your custom hook code. This code is sent to liblab when the SDK is generated. The presence of the hooks folder is all liblab requires to include hooks in your SDK.

Hooks for specific programming languages

To add hooks for a single language, run the following command:

liblab hooks add --language=<language>

If you are creating hooks for a Terraform provider, you will get an additional folder called customPlanModifiers which contains the hooks for the internal Go SDK that is used by the Terraform provider. Access the Terraform provider hooks and custom plan modifiers documentation for additional information.

Hooks can be written for the underlying Go SDK that is used by the Terraform provider by updating the code in the hooks/terraform folder. These hooks are written in the same way as writing hooks for the Go SDK.

You can read more about adding hooks in our CLI hooks documentation.

Implement hooks

In the hooks folder, you will find hooks code for each of the programming languages you have generated.

typescript
├── src
│ └── hook.ts
│ └── custom-hook.ts

After response

The after response hook is called once the response has been received from the SDK. The hook receives the request object, and the response object. The response object contains the response body as JSON, the headers, and the status code.

In this hook you can modify the response body or headers, and the changes will be returned to the SDK caller.

The HttpResponse class lives in the hook.ts file:

hook.ts
export interface HttpResponse<T> {
data?: T;
metadata: HttpMetadata;
raw: ArrayBuffer;
}

The afterResponse method is implemented in the CustomHook class in the custom-hook.ts file:

custom-hook.ts
public async afterResponse(request: HttpRequest, response: HttpResponse<any>, params: Map<string, string>): Promise<HttpResponse<any>> {
return response;
}

On error

The on error hook is called if the API returns an error, such as a 4xx status code. This hook passes the original request object for reference, along with details of the error.

The HttpError class lives in the hook.ts file:

hook.ts
export interface HttpError {
error: string;
metadata: HttpMetadata;
}

The onError method is implemented in the CustomHook class in the custom-hook.ts file:

custom-hook.ts
public async onError(request: HttpRequest, response: HttpResponse<any>, params: Map<string, string>): Promise<HttpError> {
return new CustomHttpError('a custom error message', response.metadata);
}

Hook dependencies

Each hook project has relevant files to add dependencies, for example in a Python hook there is a requirements.txt file, in Java there is a pom.xml. If you want to add any dependencies to your hooks code, for example an SDK to add telemetry, you must add them to the relevant file so that they can be picked up during the SDK generation process.

note

If you do not add dependencies to these files, the SDK generation will not know to add them and your final SDK may not build or run

Before request

The before request hook is called just before the request is sent to your API. The hook receives a request object with the URL being called, the relevant verb (GET, POST etc.), the body as JSON, and the headers.

In this hook, you can modify the request object or the headers, and the changes will be sent to your API.

The HttpRequest class lives in the hook.ts file:

hook.ts
export interface HttpRequest {
method: HttpMethod;
path: string;
headers?: Map<string, unknown>;
body?: BodyInit;
abortSignal?: AbortSignal;
queryParams?: Map<string, unknown>;
}

The beforeRequest method is implemented in the CustomHook class in the custom-hook.ts file:

custom-hook.ts
public async beforeRequest(request: HttpRequest, params: Map<string, string>): Promise<HttpRequest> {
return request;
}

Additional constructor parameters

info

The constructor parameters functionality isn't available for all programming languages.

Supported SDK languages and versions:

TypeScriptPythonJavaC#GoTerraformPHP

If you need to pass additional data from the code that calls your SDK into hooks, you can enable this by adding additional constructor parameters to your SDK client. These are defined in your liblab config file.

For example, if you wanted to define a client Id and client secret for oAuth that is used by your custom hooks code to authenticate requests, you could set this option in your config file like this:

{
...
"languageOptions": {
"typescript": {
"additionalConstructorParameters": [
{
"name": "client-id",
"example": "myClientId"
},
{
"name": "client-secret",
"example": "an-example-client-secret"
}
]
}
}
...
}

This would add the following parameters to the SDK client constructor config parameter:

class SDKName {
constructor(
config: {
...
clientId?: string;
clientSecret?: string;
},
...
) {
...
}

}

These parameters are passed to the params parameter of the hooks beforeRequest, afterResponse, and onError methods. For example, in the beforeRequest method:

export class CustomHook implements Hook {
beforeRequest(request: HttpRequest, params: Map<string, string>): HttpRequest {
// Get the client Id and secret from the params
const clientId = params.get("clientId");
const clientSecret = params.get("clientSecret");
if(!clientId || !clientSecret) {
throw new Error("clientId and clientSecret are required");
}
return request;
}
}

Build your SDK with hooks

The next time you run the liblab build command, liblab will upload the code in the hooks folder to the servers, and your custom code will be automatically integrated into the generated SDKs. Any package dependencies required by your hooks will be merged with the SDK dependencies.

Add hooks to source control

Make sure to add the hooks folder to your source control. This ensures your custom hook code is always available when building your SDKs. The folder should be in the same directory as your liblab configuration file.

Remove hooks

You can remove hooks by running the liblab hooks remove command or by manually deleting the hooks folder. After doing this, the next time you run liblab build, the SDK will be generated without your custom hook code.

note

If your configuration file includes terraform as one of the languages, the liblab hooks remove command will also delete the customPlanModifiers directory.