httpreq

package
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package httpreq exposes a single model-callable HTTP-request tool. It wraps go-resty as the transport and enforces host, method, redirect, timeout, and response-size policy at one client boundary.

The allowlist is mandatory — there is no "allow all" mode. Callers MUST enumerate the hosts the LLM is permitted to reach.

Index

Examples

Constants

View Source
const (
	DefaultTimeout          = 30 * time.Second
	DefaultMaxResponseBytes = int64(256 * 1024)
	MaxRequestTimeout       = 2 * time.Minute
)

Exported defaults keep constructor behavior visible and overridable.

Variables

View Source
var (
	ErrNilClient             = errors.New("httpreq: client must not be nil")
	ErrNilRequest            = errors.New("httpreq: request must not be nil")
	ErrMissingAllowedHosts   = errors.New("httpreq: allowed hosts must not be empty; configure an explicit network allowlist")
	ErrInvalidClientConfig   = errors.New("httpreq: client configuration is invalid")
	ErrInvalidHostPattern    = errors.New("httpreq: host pattern is invalid")
	ErrEmptyURL              = errors.New("httpreq: url must not be empty")
	ErrInvalidURL            = errors.New("httpreq: url must be an absolute http(s) URL")
	ErrInvalidMethod         = errors.New("httpreq: method must be GET, HEAD, POST, PUT, PATCH, or DELETE")
	ErrInvalidRequestTimeout = errors.New("httpreq: timeout_ms must be between 1 and 120000 when set")
	ErrHostNotAllowed        = errors.New("httpreq: host is not allowed by client policy")
	ErrMethodNotAllowed      = errors.New("httpreq: method is not allowed by client policy")
	ErrRedirectLimitReached  = errors.New("httpreq: redirect limit reached")
)

Functions

This section is empty.

Types

type Allowlist

type Allowlist struct {
	// contains filtered or unexported fields
}

Allowlist is a compiled host policy. Exact and leading-wildcard patterns share the same case, trailing-dot, IP, and IDNA normalization as request hosts. The zero value allows nothing.

func NewAllowlist

func NewAllowlist(hosts []string) (Allowlist, error)

NewAllowlist compiles host patterns once so every request is matched against normalized forms rather than raw strings. Comparing hosts textually is what lets case, a trailing dot, or an IDNA variant slip past a filter that looks correct.

Example
package main

import (
	"fmt"

	"github.com/Tangerg/scope/tools/httpreq"
)

func main() {
	allowlist, err := httpreq.NewAllowlist([]string{"api.example.com", "*.services.example.com"})
	if err != nil {
		panic(err)
	}

	fmt.Println(
		allowlist.Allows("API.EXAMPLE.COM"),
		allowlist.Allows("search.services.example.com"),
		allowlist.Allows("example.net"),
	)
}
Output:
true true false

func (Allowlist) Allows

func (a Allowlist) Allows(host string) bool

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client executes requests through an immutable network and resource policy.

func NewClient

func NewClient(config ClientConfig) (*Client, error)

NewClient fails closed: without an allowlist there is no host a model- supplied URL may reach. The alternative — an empty allowlist meaning unrestricted — turns a forgotten configuration line into an open proxy.

func (*Client) Do

func (c *Client) Do(ctx context.Context, request *Request) (*Response, error)

Do applies the frozen host, method, timeout, redirect, and response-size policy before returning a model-facing response.

type ClientConfig

type ClientConfig struct {
	// AllowedHosts accepts exact hosts and one leading wildcard, such as
	// "api.example.com" or "*.example.com". A wildcard does not match its root.
	AllowedHosts []string

	// AllowedMethods defaults to GET and HEAD. Comparison is case-insensitive.
	AllowedMethods []Method

	// DefaultHeaders are added unless [Request.Headers] overrides them.
	DefaultHeaders map[string]string

	// MaxResponseBytes selects [DefaultMaxResponseBytes] at zero.
	MaxResponseBytes int64

	// DefaultTimeout selects [DefaultTimeout] at zero.
	DefaultTimeout time.Duration

	// HTTPClient supplies caller-owned transport, cookie jar, proxy, and TLS
	// settings. NewClient clones the value before installing redirect policy.
	HTTPClient *http.Client
}

ClientConfig defines the network authority and resource bounds frozen into a Client. AllowedHosts is mandatory because the zero policy denies network access rather than silently opening it.

func (ClientConfig) Validate

func (c ClientConfig) Validate() error

type Method

type Method string

Method is an HTTP method exposed by the tool contract.

const (
	MethodGET    Method = http.MethodGet
	MethodHEAD   Method = http.MethodHead
	MethodPOST   Method = http.MethodPost
	MethodPUT    Method = http.MethodPut
	MethodPATCH  Method = http.MethodPatch
	MethodDELETE Method = http.MethodDelete
)

Methods are an allowlist rather than a pass-through, because the tool decides what a model may do to a remote host. An unlisted method is refused before the request is built.

func (Method) Normalize

func (m Method) Normalize() Method

Normalize applies the wire default and canonical HTTP casing.

func (Method) Validate

func (m Method) Validate() error

type Request

type Request struct {
	URL       string            `json:"url" jsonschema:"minLength=1" jsonschema_description:"Absolute http(s) URL. Host must match the configured allowlist."`
	Method    Method            `` /* 229-byte string literal not displayed */
	Headers   map[string]string `` /* 136-byte string literal not displayed */
	Query     map[string]string `json:"query,omitempty" jsonschema_description:"Optional query parameters appended to the URL."`
	Body      string            `` /* 143-byte string literal not displayed */
	TimeoutMS int               `` /* 178-byte string literal not displayed */
}

Request is the model-facing argument shape, and its struct tags are the contract the model actually sees. The schema is derived from this type so the description a model reads and the fields the tool decodes cannot drift apart.

func (*Request) Validate

func (r *Request) Validate() error

type Response

type Response struct {
	Status    int                 `json:"status"`
	Headers   map[string][]string `json:"headers,omitempty"`
	Body      string              `json:"body"`
	Truncated bool                `json:"truncated,omitempty"`
	// Duration includes transport execution, body reading, and body closure.
	Duration string `json:"duration"`
}

Response is the model-facing result. Body remains text so binary or structured payload interpretation stays with the caller.

type Tool

type Tool struct {
	// contains filtered or unexported fields
}

Tool adapts a configured Client to the tool contract. It takes a concrete client rather than an interface because the allowlist, method restrictions, and timeouts are the point of this tool; a substitutable transport would let a caller bypass them.

func NewTool

func NewTool(client *Client) (*Tool, error)

NewTool rejects a nil client so a tool cannot be advertised to a model before the restrictions that make it safe exist.

func (*Tool) Call

func (t *Tool) Call(ctx context.Context, invocation toolcontract.Invocation) (chat.ToolOutput, error)

func (*Tool) Definition

func (t *Tool) Definition() chat.ToolDefinition

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL