Skip to content

HTTP Client Options

Configuration for HTTP Types - composite types that enable PostgreSQL functions to make HTTP requests to external APIs.

Overview

json
{
  "NpgsqlRest": {
    "HttpClientOptions": {
      "Enabled": false,
      "ResponseStatusCodeField": "status_code",
      "ResponseBodyField": "body",
      "ResponseHeadersField": "headers",
      "ResponseContentTypeField": "content_type",
      "ResponseSuccessField": "success",
      "ResponseErrorMessageField": "error_message"
    }
  }
}

Settings Reference

SettingTypeDefaultDescription
EnabledboolfalseEnable HTTP client functionality for annotated composite types.
ResponseStatusCodeFieldstring"status_code"Field name for HTTP response status code.
ResponseBodyFieldstring"body"Field name for HTTP response body content.
ResponseHeadersFieldstring"headers"Field name for HTTP response headers (as JSON).
ResponseContentTypeFieldstring"content_type"Field name for Content-Type header value.
ResponseSuccessFieldstring"success"Field name for success flag (true for 2xx status codes).
ResponseErrorMessageFieldstring"error_message"Field name for error message if request failed.

How HTTP Types Work

HTTP Types allow PostgreSQL functions to make HTTP requests to external APIs. When a function parameter uses a composite type with an HTTP definition comment, NpgsqlRest automatically:

  1. Parses the HTTP definition from the type comment
  2. Substitutes placeholders with function parameter values
  3. Executes the HTTP request
  4. Populates the type fields with response data
  5. Executes the PostgreSQL function with the populated parameter

Creating an HTTP Type

Step 1: Create a Composite Type

Create a composite type with fields matching the response field names:

sql
create type weather_api as (
    body text,
    status_code int,
    headers json,
    content_type text,
    success boolean,
    error_message text
);

Step 2: Add HTTP Definition Comment

Add an HTTP definition as a comment on the type (RFC 7230 format):

sql
comment on type weather_api is 'GET https://api.weather.com/v1/current?city={_city}
Authorization: Bearer {_api_key}
timeout 30s';

Step 3: Use in a Function

Create a function with the HTTP type as a parameter:

sql
create function get_weather(
  _city text,
  _api_key text,
  _req weather_api
)
returns json
language plpgsql
as $$
begin
    if (_req).success then
        return (_req).body::json;
    else
        return json_build_object('error', (_req).error_message);
    end if;
end;
$$;

HTTP Definition Format

The comment on the composite type follows a simplified HTTP message format similar to .http files:

METHOD URL [HTTP/version]
Header-Name: Header-Value
...

[request body]

Supported Methods

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

Example Definitions

Simple GET request:

sql
comment on type api_response is 'GET https://api.example.com/data';

GET with headers:

sql
comment on type api_response is 'GET https://api.example.com/data
Authorization: Bearer {_token}
Accept: application/json';

POST with body:

sql
comment on type api_response is 'POST https://api.example.com/users
Content-Type: application/json

{"name": "{_name}", "email": "{_email}"}';

Timeout Directives

Timeout can be specified before or after the request line using interval format:

sql
-- Before request line
comment on type api_response is 'timeout 30
GET https://api.example.com/data';

-- After headers
comment on type api_response is 'GET https://api.example.com/data
Authorization: Bearer {_token}
timeout 30s';

Common timeout formats:

FormatExampleDescription
Seconds (integer)timeout 3030 seconds
Seconds with suffixtimeout 30s30 seconds
TimeSpan formattimeout 00:00:3030 seconds
With @ prefix@timeout 2min2 minutes

Response Fields

The composite type fields are automatically populated based on their names:

Field NameTypeDescription
bodytextResponse body content
status_codeint or textHTTP status code (e.g., 200, 404)
headersjsonResponse headers as JSON object
content_typetextContent-Type header value
successbooleanTrue for 2xx status codes
error_messagetextError message if request failed

You can customize field names via HttpClientOptions configuration if your type uses different names.

Placeholder Substitution

URLs, headers, and request body can contain placeholders in the format {parameter_name}. These placeholders are automatically replaced with the values of other function parameters that share the same name.

sql
-- Type with placeholders
comment on type weather_api is 'GET https://api.weather.com/v1/current?city={_city}
Authorization: Bearer {_api_key}
timeout 30s';

-- Function with matching parameter names
create function get_weather(
  _city text,        -- Value substitutes {_city} placeholder
  _api_key text,     -- Value substitutes {_api_key} placeholder
  _req weather_api   -- HTTP type parameter (receives response)
)
returns json
...

When calling GET /api/get-weather?_city=London&_api_key=secret123, NpgsqlRest will:

  1. Substitute {_city} with London and {_api_key} with secret123
  2. Make the HTTP request to https://api.weather.com/v1/current?city=London with header Authorization: Bearer secret123
  3. Populate the _req parameter fields with the response data
  4. Execute the PostgreSQL function

Complete Example

Configuration

json
{
  "NpgsqlRest": {
    "HttpClientOptions": {
      "Enabled": true
    }
  }
}

SQL Setup

sql
-- Create response type
create type github_api as (
    body text,
    status_code int,
    headers json,
    content_type text,
    success boolean,
    error_message text
);

-- Define HTTP request
comment on type github_api is 'GET https://api.github.com/users/{_username}
Accept: application/vnd.github.v3+json
User-Agent: NpgsqlRest
timeout 10s';

-- Create function
create function get_github_user(
    _username text,
    _response github_api
)
returns json
language plpgsql
as $$
begin
    if (_response).success then
        return (_response).body::json;
    else
        return json_build_object(
            'error', true,
            'status', (_response).status_code,
            'message', (_response).error_message
        );
    end if;
end;
$$;

comment on function get_github_user(text, github_api) is 'HTTP GET /github/user';

Usage

GET /github/user/octocat

Returns the GitHub user data or an error response.

Next Steps

Comments

Released under the MIT License.