Help us shape the future of Go! Take the 2026 Go Developer Survey

gapi

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Overview

Package gapi holds what Google Cloud services share: the REST mirror that maps JSON/HTTP calls onto a service's gRPC handlers, Google-style errors, and the long-running operations service (google.longrunning.Operations).

Index

Constants

View Source
const KeyID = "pogi"

KeyID is the kid of the shared signing key.

View Source
const MaxPageSize = 1000

MaxPageSize is the largest page Page returns; Google caps a bigger page size instead of refusing it. (A negative size is refused earlier, in invoke.)

Variables

View Source
var EmptyEtag = []byte{0, 0, 1}

EmptyEtag is the etag of a policy that was never set.

View Source
var Regions = []string{"us-central1", "us-east1", "us-east4", "us-west1", "us-west2", "europe-west1", "europe-west2", "europe-west3",
	"europe-west4", "asia-east1", "asia-northeast1", "asia-south1", "asia-southeast1", "australia-southeast1", "southamerica-east1"}

Regions are the Google Cloud regions pogi lists: Compute Engine's regions, Cloud Tasks' locations.

Functions

func AccessToken

func AccessToken(email, scope string, ttl time.Duration) string

AccessToken returns an opaque ya29 access token that carries its email, scope and expiry, authenticated so Token reads it back. Nothing is stored.

func Bool added in v0.2.0

func Bool(v string) bool

Bool reads a true/false query value. Google accepts any case, and the Python clients send True.

func Cert

func Cert(k *rsa.PrivateKey, cn string) []byte

Cert makes a self-signed X.509 certificate (DER) for a key, as Google publishes for service account keys.

func Client

func Client(h *core.Hub) *http.Client

Client is the HTTP client for calls a service makes to user targets (Cloud Tasks, Scheduler, Eventarc). A *.localhost host (<svc>.run.localhost) goes to pogi's own port with its Host header kept, so no DNS is involved. It follows no redirects: a 3xx is a failed delivery, as at Google.

func Decode

func Decode(msg proto.Message, in map[string]any) error

Decode fills a request message from the JSON members in. It refuses an unknown enum name and a negative page_size, as Google does. Unknown fields are dropped.

func Err

func Err(w http.ResponseWriter, c *core.Ctx, err error)

Err renders a gRPC status as a Google REST error.

func Exists

func Exists(format string, a ...any) error

Exists is an ALREADY_EXISTS status.

func Invalid

func Invalid(format string, a ...any) error

Invalid is an INVALID_ARGUMENT status.

func JSON

func JSON(w http.ResponseWriter, out any)

JSON writes a 200 response: protojson for a proto message, encoding/json for the rest.

func JSONErr

func JSONErr(w http.ResponseWriter, c *core.Ctx, code int, name, msg string)

JSONErr writes {"error": {"code", "message", "status"}}.

func JWK

func JWK(kid string, pub *rsa.PublicKey) map[string]any

JWK is the JSON Web Key of an RSA public key.

func NotFound

func NotFound(format string, a ...any) error

NotFound is a NOT_FOUND status.

func OAuthToken

func OAuthToken() string

OAuthToken returns an access token for no one in particular.

func OIDCToken

func OIDCToken(email, audience string) string

OIDCToken returns an RS256 ID token for the service account, as Google would send it: iss, sub, azp, email, email_verified, aud, iat and exp.

func PEM

func PEM(typ string, der []byte) []byte

PEM encodes DER bytes with the given block type.

func Page

func Page[T any](items []T, size int32, token string) ([]T, string)

Page cuts one page from a sorted list; the token is the offset of the next page.

func PageSizeOK

func PageSizeOK(v string) bool

PageSizeOK says whether v can be a maxResults query value: empty, or a whole number from 0 to 2^32-1. A bigger size is capped, a negative or non-numeric one is refused with a 400.

func ParseBody

func ParseBody(b []byte, field string) (map[string]any, error)

ParseBody reads a JSON request body into the map that Decode turns into a request. field is the request member the body fills ("" means the body is the request). A body of null is an empty message.

func PlainProto added in v0.2.0

func PlainProto(body []byte, err error) string

PlainProto says in plain words why a protojson body was refused. protojson reports "syntax error" even for a field of the wrong type, so a body that is valid JSON gets the wrong-type sentence. Go's text follows.

func Policy

func Policy(cur *iampb.Policy) *iampb.Policy

Policy returns a copy of the stored policy, or the empty one when none was set.

func ProxyDesc added in v0.2.0

func ProxyDesc(sd *grpc.ServiceDesc, conn func(context.Context) (*grpc.ClientConn, error), check func(proto.Message) error) *grpc.ServiceDesc

ProxyDesc returns a copy of a generated service description whose methods forward every call to another gRPC server: a vendor's emulator that runs behind pogi. Register it with a nil implementation. conn is called on each call and may start the backend; its error is the call's error. check, if not nil, sees each request first and may refuse it. Methods that stream from the client are left out (the server answers Unimplemented): the backends here (Spanner, Bigtable's emulator) have none.

func PublicKey

func PublicKey() *rsa.PublicKey

PublicKey verifies the tokens OIDCToken makes.

func SetPolicy

func SetPolicy(cur, in *iampb.Policy) (*iampb.Policy, error)

SetPolicy returns the policy to store when in replaces cur (nil if never set). A non-empty etag that isn't cur's is a concurrent change, as at Google. Bindings without members are dropped.

func SetSigningKey

func SetSigningKey(k *rsa.PrivateKey)

SetSigningKey installs a saved signing key.

func SignJWT

func SignJWT(kid string, k *rsa.PrivateKey, claims any) string

SignJWT signs claims with RS256.

func SigningKey

func SigningKey() *rsa.PrivateKey

SigningKey is pogi's stand-in for Google's own ID-token key. It signs every ID token (OIDCToken: IAM Credentials, the token endpoint, Cloud Tasks and Scheduler) and its public half is served at /oauth2/v3/certs. It is made on first use; the IAM service keeps it across restarts with SetSigningKey.

func Status

func Status(httpCode int, err error) *spb.Status

Status is the google.rpc.Status of a delivery: OK for 2xx, otherwise the gRPC code Google maps the HTTP status to (httpCode 0 means no response, err says why).

func Update

func Update(dst, src proto.Message, paths []string, allowed ...string) error

Update copies the fields an update mask names from src to dst. An empty mask means the allowed fields that src sets, and "*" means all allowed fields.

Types

type Filter

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

Filter is a parsed Google filter expression, in the syntax Cloud Logging and Cloud Monitoring share: terms joined by AND (or just a space) and OR, NOT or -, and parentheses. OR binds tighter than AND, as in Logging.

field OP value      OP is one of = != > >= < <= : =~ !~
field = fn(a, b)    a value function (Monitoring: starts_with, one_of, ...)
fn(a, b)            a function alone (Logging: log_id("x"))
word, "a phrase"    a global text search

The service gives the terms their meaning: see Match.

func ParseFilter

func ParseFilter(s string) (*Filter, error)

ParseFilter parses a filter; the empty filter matches everything.

func (*Filter) Match

func (f *Filter) Match(term func(field, op, value string) bool, text func(string) bool) bool

Match evaluates the filter. term decides "field op value" (a value function gives op "fn", or "!fn" for !=, and its arguments joined by NUL as the value; a function alone gives field "fn" and op "()"), and text decides a global search.

type JWT

type JWT struct {
	Header, Claims map[string]any
	// contains filtered or unexported fields
}

JWT is a parsed compact JWT whose signature has not been checked.

func ParseJWT

func ParseJWT(s string) (*JWT, error)

ParseJWT splits and decodes a compact JWT.

func (*JWT) Exp

func (j *JWT) Exp() time.Time

Exp is the exp claim as a time (zero when absent).

func (*JWT) Str

func (j *JWT) Str(claim string) string

Str is a string claim ("" when absent).

func (*JWT) Verify

func (j *JWT) Verify(pub *rsa.PublicKey) bool

Verify checks the RS256 signature.

type KeyDirectory

type KeyDirectory interface {
	// ServiceAccountKeys returns the enabled public keys of an enabled
	// service account by key id; nil when it doesn't exist or is disabled.
	ServiceAccountKeys(email string) map[string]*rsa.PublicKey
}

KeyDirectory is what the IAM service offers the token endpoint.

type Mux

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

Mux serves Rules by calling a service's gRPC handlers, the way REST does.

func NewMux

func NewMux(impl any, rules ...Rule) *Mux

NewMux compiles the rules.

func (*Mux) Match

func (m *Mux) Match(r *http.Request) bool

Match is for core.Info.Match.

func (*Mux) ServeHTTP

func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Ops

type Ops struct {
	longrunningpb.UnimplementedOperationsServer
	// contains filtered or unexported fields
}

Ops is the shared google.longrunning.Operations service: every GCP service that returns an Operation stores it here, and clients poll it by name over gRPC or REST (GET /v1|v2/projects/p/locations/l/operations/o).

ponytail: operations are in memory only and never expire; persist them if a restart mid-operation ever matters.

func NewOps

func NewOps(*core.Hub) *Ops

NewOps creates the operations service.

func Operations

func Operations(h *core.Hub) *Ops

Operations returns the hub's operations service, or a detached one when "operations" is disabled (clients then can't poll, but done ops still work).

func (*Ops) CancelOperation

func (o *Ops) CancelOperation(ctx context.Context, r *longrunningpb.CancelOperationRequest) (*emptypb.Empty, error)

CancelOperation marks a running operation CANCELLED; the work itself runs on.

func (*Ops) Delegate added in v0.2.0

func (o *Ops) Delegate(client func() longrunningpb.OperationsClient)

Delegate adds a backend for the operations that are not stored here: the emulator behind a service (Spanner's) keeps its own. client returns nil while the backend is not running, and then it knows no operation.

func (*Ops) DeleteOperation

func (o *Ops) DeleteOperation(ctx context.Context, r *longrunningpb.DeleteOperationRequest) (*emptypb.Empty, error)

func (*Ops) Done

func (o *Ops) Done(parent string, meta, resp proto.Message) *longrunningpb.Operation

Done records a finished operation under parent (projects/p/locations/l, or "" for a top-level operations/<id>) with resp as its result; meta may be nil.

func (*Ops) DoneJSON added in v0.2.0

func (o *Ops) DoneJSON(parent string, meta, resp map[string]any) map[string]any

DoneJSON records a finished operation under parent whose metadata and response are JSON objects (a generic REST engine's resources, which no proto message describes). A GET or :wait of it answers {"name", "metadata", "done": true, "response"}; list, cancel and delete treat it like any other.

func (*Ops) Info

func (o *Ops) Info() core.Info

func (*Ops) RegisterGRPC

func (o *Ops) RegisterGRPC(g *grpc.Server)

func (*Ops) Reset

func (o *Ops) Reset()

func (*Ops) ServeHTTP

func (o *Ops) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*Ops) Start

func (o *Ops) Start(parent string, meta proto.Message, run func() (proto.Message, error)) *longrunningpb.Operation

Start records a running operation and finishes it with run's result in the background; Get and Wait see it as done once run returns.

type REST

type REST struct {
	Versions    []string // path versions, e.g. {"v2"}
	Collections []string // first collection after projects/<p>[/locations/<l>] that this service claims
	Desc        *grpc.ServiceDesc
	Impl        any // the gRPC server implementation
	Routes      map[string]Route
}

REST serves a Google API's REST surface by calling its gRPC handlers.

Routes are keyed "VERB shape[:verb]", where shape is the path after /<version>/projects/<p>/ with every resource id replaced by "*":

"POST locations/*/services"          → parent = projects/p/locations/l
"GET locations/*/services/*"         → name   = projects/p/locations/l/services/s
"POST locations/*/jobs/*:run"        → name   = projects/p/locations/l/jobs/j

The resource name is the path up to its last even segment, so collection calls get the parent and item calls get the item. Query parameters become request fields by their JSON names (serviceId, pageSize, updateMask).

func (*REST) Match

func (a *REST) Match(r *http.Request) bool

Match is for core.Info.Match.

func (*REST) ServeHTTP

func (a *REST) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*REST) Split

func (a *REST) Split(path string) (project string, parts []string, ok bool)

Split parses /<version>/projects/<p>/<rest...>; parts keeps locations/<l>.

type Route

type Route struct {
	Method string            // gRPC method name, e.g. "CreateService"
	Field  string            // request field the path's resource name fills, dotted ("parent", "service.name")
	Body   string            // request field the JSON body fills; "" means the whole body is the request
	Desc   *grpc.ServiceDesc // overrides REST.Desc for services with several gRPC services
}

Route maps one REST call onto a gRPC method.

type Rule

type Rule struct {
	HTTP   string
	Method string // gRPC method name; with Fn, the operation name shown in the request log
	Body   string // request field the JSON body fills; "" means the whole body is the request
	// Fn handles the call instead of a gRPC method: r has the body in
	// core.Body(r) and vars holds the path variables. A proto.Message is
	// answered as protojson, anything else as plain JSON.
	Fn func(r *http.Request, vars map[string]string) (any, error)
}

Rule is one REST call, written as in a google.api.http annotation:

"POST /v1/{name=projects/*/serviceAccounts/*}:disable"

"*" is one path segment and "**" the rest of the path. A {variable} fills the request field of that (dotted, JSON) name with the segments it covers. It is the Mux's answer to REST paths that REST's projects/<p>/<collection> shape can't express: organizations, top-level collections, ids without a "projects/" prefix.

type Token

type Token struct {
	Email, Scope string
	Expires      time.Time
}

Token is what an access token carries.

func ParseAccessToken

func ParseAccessToken(s string) (t Token, ok bool)

ParseAccessToken reads a token made by AccessToken; ok is false for any other string, and for one that has expired.

Jump to

Keyboard shortcuts

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