remote

package module
v0.3.0 Latest Latest
Warning

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

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

README

remote

Registry-based outbound HTTP client manager. Services (external agencies, backend APIs) are declared in a JSON config file; the manager resolves endpoints, applies authentication, and executes requests — no per-service boilerplate in your application code.

Usage

import "github.com/OpenNSW/core/remote"

manager := remote.NewManager()
if err := manager.LoadServices("configs/services.json"); err != nil {
    log.Fatal(err)
}

// Call a registered service
var result MyResponseType
err := manager.Call(ctx, "npqs-api", remote.Request{
    Method: http.MethodPost,
    Path:   "/v1/applications",
    Body:   myPayload,
}, &result)

Services config

services.json declares available services with their endpoint, timeout, and authentication:

{
  "version": "1",
  "services": [
    {
      "id": "npqs-api",
      "url": "https://npqs.example.gov/api",
      "timeout_seconds": 30,
      "auth": {
        "type": "oauth2",
        "options": {
          "token_url": "https://idp.example.gov/token",
          "client_id": "my-client",
          "client_secret": "secret",
          "scopes": ["npqs:submit"]
        }
      }
    },
    {
      "id": "legacy-api",
      "url": "https://legacy.example.gov",
      "timeout_seconds": 10,
      "auth": {
        "type": "api_key",
        "options": {
          "key": "X-API-Key",
          "value": "my-api-key"
        }
      }
    }
  ]
}

Authentication strategies

See remote/auth for the full reference. Supported types:

type Description
api_key Static header (e.g. X-API-Key: value)
bearer Authorization: Bearer <token>
oauth2 Client credentials flow with automatic token caching

Direct client access

client, err := manager.GetClient("npqs-api")

// Execute a pre-built *http.Request directly
resp, err := client.Do(req)

Listing registered services

ids := manager.ListServices() // []string{"npqs-api", "legacy-api"}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRequestFailed      = errors.New("remote: request failed")
	ErrTimeout            = errors.New("remote: request timed out")
	ErrServiceUnavailable = errors.New("remote: service unavailable")
	ErrUnauthorized       = errors.New("remote: unauthorized access")
	ErrBadRequest         = errors.New("remote: invalid request")
	ErrNotFound           = errors.New("remote: resource not found")
)
View Source
var DefaultRetryConfig = RetryConfig{
	MaxRetries:     3,
	InitialBackoff: 500 * time.Millisecond,
	MaxBackoff:     10 * time.Second,
	RetryableStatus: []int{
		http.StatusTooManyRequests,
		http.StatusInternalServerError,
		http.StatusBadGateway,
		http.StatusServiceUnavailable,
		http.StatusGatewayTimeout,
	},
}

DefaultRetryConfig provides a sensible default for most services.

Functions

This section is empty.

Types

type AuthConfig

type AuthConfig struct {
	Type    string          `json:"type"` // "api_key", "oauth2", "bearer"
	Options json.RawMessage `json:"options"`
}

type Client

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

func NewClient

func NewClient(baseURL string, opts ...Option) *Client

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, body io.Reader, extraHeaders map[string]string, retry *RetryConfig) (*http.Response, error)

func (*Client) JSONRequest

func (c *Client) JSONRequest(ctx context.Context, req Request, response interface{}) error

func (*Client) RawRequest added in v0.3.0

func (c *Client) RawRequest(ctx context.Context, req RawRequest) (*RawResponse, error)

RawRequest sends req.Body verbatim and returns the raw response. Unlike JSONRequest, a non-2xx status is NOT an error: protocols like SOAP deliver faults as HTTP 500 with a meaningful body, so the caller interprets the status and body together. The returned error is transport-level only (connection, timeout, auth application). The response body read is capped at maxRawResponseBytes.

type Manager

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

func NewManager

func NewManager() *Manager

func (*Manager) Call

func (m *Manager) Call(ctx context.Context, serviceID string, req Request, response interface{}) error

func (*Manager) CallRaw added in v0.3.0

func (m *Manager) CallRaw(ctx context.Context, serviceID string, req RawRequest) (*RawResponse, error)

CallRaw sends a raw-bodied request (e.g. a SOAP/XML envelope) to a registered service. See Client.RawRequest for the error semantics: a non-2xx status is returned in the response, not as an error.

func (*Manager) GetClient

func (m *Manager) GetClient(id string) (*Client, error)

func (*Manager) GetClientByURL

func (m *Manager) GetClientByURL(rawURL string) (*Client, string, error)

func (*Manager) ListServices

func (m *Manager) ListServices() []string

func (*Manager) LoadServices

func (m *Manager) LoadServices(filePath string) error

type Option

type Option func(*Client)

func WithAuthenticator

func WithAuthenticator(a auth.Authenticator) Option

func WithClientCertificate added in v0.3.0

func WithClientCertificate(cert tls.Certificate) Option

WithClientCertificate presents a fixed certificate during the TLS handshake (mTLS). For material that rotates on disk, prefer WithClientCertificateFiles.

func WithClientCertificateFiles added in v0.3.0

func WithClientCertificateFiles(certFile, keyFile string) Option

WithClientCertificateFiles presents the client certificate at certFile / keyFile during the TLS handshake (mTLS). The PEM files are read on each handshake — a per-connection, not per-request, cost — so rotated material is picked up by new connections with no restart (zero-downtime rotation), and a missing or malformed file fails the call with a clear error.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

type RawRequest added in v0.3.0

type RawRequest struct {
	Method      string
	Path        string
	ContentType string // sent as Content-Type when Body is non-empty
	Body        []byte
	Headers     map[string]string
	Retry       *RetryConfig // If nil, no retries will be performed
}

RawRequest bundles the caller-provided parts of an outbound call whose body is sent verbatim — no JSON marshalling — e.g. a SOAP/XML envelope.

type RawResponse added in v0.3.0

type RawResponse struct {
	StatusCode int
	Header     http.Header
	Body       []byte
}

RawResponse is the undecoded outcome of a RawRequest.

type Registry

type Registry struct {
	Version  string          `json:"version"`
	Services []ServiceConfig `json:"services"`
}

type RemoteError

type RemoteError struct {
	StatusCode int
	Message    string
	Wrapped    error
}

func (*RemoteError) Error

func (e *RemoteError) Error() string

func (*RemoteError) Unwrap

func (e *RemoteError) Unwrap() error

type Request

type Request struct {
	Method  string
	Path    string
	Query   url.Values
	Body    any
	Headers map[string]string
	Retry   *RetryConfig // If nil, no retries will be performed
}

Request bundles all the caller-provided parts of an outbound call.

type RetryConfig

type RetryConfig struct {
	MaxRetries      int           // Maximum number of retries (0 = no retries)
	InitialBackoff  time.Duration // Time to wait before the first retry
	MaxBackoff      time.Duration // Maximum wait time between retries
	RetryableStatus []int         // HTTP status codes that should trigger a retry
}

RetryConfig defines the strategy for retrying failed requests.

type ServiceConfig

type ServiceConfig struct {
	ID      string       `json:"id"`
	URL     string       `json:"url"`
	Timeout string       `json:"timeout"`
	Auth    *AuthConfig  `json:"auth,omitempty"`
	TLS     *TLSSettings `json:"tls,omitempty"`
}

type TLSSettings added in v0.3.0

type TLSSettings struct {
	ClientCertFile string `json:"client_cert_file"`
	ClientKeyFile  string `json:"client_key_file"`
}

TLSSettings configures transport-level client authentication (mTLS) for a service. Both values are filesystem paths to PEM files, not secret references: certificate chains routinely exceed the 4 KB cap that auth.SecretRef places on file-sourced secrets.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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