Skip to content

Latest commit

 

History

History
89 lines (68 loc) · 3.39 KB

http-auth.md

File metadata and controls

89 lines (68 loc) · 3.39 KB
description How to serve a VGI worker over HTTP and authenticate callers with bearer tokens or JWT/OAuth.

Serve over HTTP with authentication

What this is: how to run a worker over HTTP instead of a subprocess, and gate it with authentication.
Who it's for: developers deploying a worker as a network service.
Requires: pip install vgi-python[http] (and [oauth] for JWT).

Prerequisites

  • A working worker (see the tutorial).
  • pip install vgi-python[http]; for JWT/OAuth also vgi-python[oauth].

Serve over HTTP

The same worker that runs over a subprocess also runs over HTTP — add --http:

vgi-serve my_worker.py --http

DuckDB still attaches the worker over HTTP the usual way (ATTACH ... (TYPE vgi, LOCATION 'http://...')). You only need the Python Client when you're calling the worker from Python rather than from SQL — for tests, scripts, or another service. It connects with transport="http" instead of spawning a subprocess, and exposes the same call methods:

# illustrative — calling the worker from Python over HTTP
from vgi.client import Client

with Client(transport="http", base_url="http://localhost:8080", bearer_token="token1") as client:
    ...  # same .scalar_function() / .table_function() calls as the subprocess transport

The native client advertises a 256 MiB decoded-response limit on every RPC, including the short-lived connections used for catalog operations. Override it when the application has a smaller memory budget:

with Client.from_http(
    "http://localhost:8080",
    accepted_max_response_bytes=32 * 1024 * 1024,
) as client:
    ...

The value must be an integer from 65536 through 2^53 - 1. Configured clients discover server support before the first RPC and fail closed if it is absent. Passing None omits negotiation for compatibility with a legacy unbounded server; doing so is not recommended for externally reachable workers. Capability discovery reports the server's own effective response cap and whether it honors the client limit.

Add authentication

The quickest setup is static bearer tokens via an environment variable — comma-separated token=principal pairs:

VGI_BEARER_TOKENS="token1=alice,token2=bob" vgi-serve my_worker.py --http

Unauthenticated requests get HTTP 401. Authenticated requests carry the principal in an AuthContext. Your function reads it through an optional ctx parameter: declare ctx in the signature and the framework injects a per-call CallContext (auth, logging, transport info) — you don't pass it from SQL.

# illustrative — reading the injected ctx in a function
class Secret(ScalarFunction):
    @classmethod
    def compute(cls, value, *, ctx) -> ...:
        ctx.auth.require_authenticated()      # raises if anonymous
        principal = ctx.auth.principal         # "alice"
        ...

For JWT/JWKS and RFC 9728 OAuth resource metadata, set VGI_JWT_ISSUER / VGI_JWT_AUDIENCE (requires vgi-python[oauth]) — see the Authentication reference for the full variable list and programmatic make_wsgi_app(authenticate=...) API.

Next steps