Documentation
¶
Overview ¶
Package http provides an HTTP server comprised of multiple HTTP services
Index ¶
- Constants
- func AppleAppSiteAssociationHandler(cfg *AppleAppSiteAssociationConfig, logger logging.Logger, ...) http.HandlerFunc
- func RegisterHTTPServer(i do.Injector, serviceName string)
- func RootLevelAssetsHandler(assetsDir string) http.HandlerFunc
- type AppleAppSiteAssociationConfig
- type Config
- type Option
- type Server
Constants ¶
const AppleAppSiteAssociationPath = "/.well-known/apple-app-site-association"
AppleAppSiteAssociationPath is the well-known path iOS fetches to discover a domain's Universal Link configuration. Apple requires it be served over HTTPS with no redirects and a JSON content type.
See https://developer.apple.com/documentation/xcode/supporting-associated-domains.
Variables ¶
This section is empty.
Functions ¶
func AppleAppSiteAssociationHandler ¶
func AppleAppSiteAssociationHandler( cfg *AppleAppSiteAssociationConfig, logger logging.Logger, tracerProvider tracing.TracerProvider, ) http.HandlerFunc
AppleAppSiteAssociationHandler returns an http.HandlerFunc that serves the apple-app-site-association document described by cfg. Register it at AppleAppSiteAssociationPath; NewHTTPServer does so automatically when Config.AppleAppSiteAssociation is enabled, so this is only needed to serve the document from somewhere else (a different mux, a CDN origin, etc).
A config that is empty or malformed yields a handler that responds 404, so callers never have to branch on whether the feature is configured.
func RegisterHTTPServer ¶
RegisterHTTPServer registers a Server with the injector. The serviceName parameter is passed directly rather than injected, since string is too generic a type to resolve unambiguously from the injector.
func RootLevelAssetsHandler ¶
func RootLevelAssetsHandler(assetsDir string) http.HandlerFunc
RootLevelAssetsHandler returns an http.HandlerFunc that serves static files from assetsDir. It only serves root-level files (no subdirectories) and guards against path traversal. Register with router.Get("/*", RootLevelAssetsHandler(assetsDir)) as the last route.
Types ¶
type AppleAppSiteAssociationConfig ¶
type AppleAppSiteAssociationConfig struct {
// TeamID is the Apple Developer Team ID (e.g. "ABCD1234XY").
TeamID string `env:"TEAM_ID" json:"teamID,omitempty" yaml:"teamID,omitempty"`
// BundleID is the iOS app bundle identifier (e.g. "com.example.ios").
BundleID string `env:"BUNDLE_ID" json:"bundleID,omitempty" yaml:"bundleID,omitempty"`
// Paths restricts which URL paths open the app, as Apple component patterns
// (e.g. "/invitations/*"). Empty grants every path on the domain, which is what a
// service with no opinion wants; set it when only part of the site should deep-link
// into the app.
Paths []string `env:"PATHS" json:"paths,omitempty" yaml:"paths,omitempty"`
// WebCredentials adds the webcredentials service to the document, which is what
// lets iOS offer Password AutoFill and shared credentials for this domain. It is
// off by default: a domain claims it only when the app's entitlements list a
// matching "webcredentials:" associated domain.
WebCredentials bool `env:"WEB_CREDENTIALS" json:"webCredentials,omitempty" yaml:"webCredentials,omitempty"`
// contains filtered or unexported fields
}
AppleAppSiteAssociationConfig holds the configuration for the apple-app-site-association file iOS uses for Universal Links. It is optional: when TeamID and BundleID are both empty the file is not served at all, so services without an iOS app are unaffected. When either is set, both are required.
func (*AppleAppSiteAssociationConfig) Enabled ¶
func (cfg *AppleAppSiteAssociationConfig) Enabled() bool
Enabled indicates whether the apple-app-site-association file should be served, which requires both identifiers to be present and well-formed. A malformed config reports disabled here and an error from ValidateWithContext, so a service that skips validation serves nothing rather than a document iOS would reject.
func (*AppleAppSiteAssociationConfig) ValidateWithContext ¶
func (cfg *AppleAppSiteAssociationConfig) ValidateWithContext(ctx context.Context) error
ValidateWithContext validates an AppleAppSiteAssociationConfig struct. An entirely empty config is valid (the feature is simply off); a partially filled one is not.
Setting any field counts as intent to serve the document, including Paths or WebCredentials alone. That matters because those two are inert without the identifiers: a config that scopes paths but whose TeamID never made it out of the environment would otherwise validate clean and then quietly serve nothing.
type Config ¶
type Config struct {
// AppleAppSiteAssociation, when populated, causes the server to serve the
// apple-app-site-association file at AppleAppSiteAssociationPath.
AppleAppSiteAssociation *AppleAppSiteAssociationConfig `` /* 133-byte string literal not displayed */
SSLCertificateFile string `env:"SSL_CERTIFICATE_FILEPATH" json:"sslCertificate,omitempty" yaml:"sslCertificate,omitempty"`
SSLCertificateKeyFile string `env:"SSL_CERTIFICATE_KEY_FILEPATH" json:"sslCertificateKey,omitempty" yaml:"sslCertificateKey,omitempty"`
StartupDeadline time.Duration `env:"STARTUP_DEADLINE" json:"startupDeadline,omitempty" yaml:"startupDeadline,omitempty"`
ReadTimeout time.Duration `env:"READ_TIMEOUT" json:"readTimeout,omitempty" yaml:"readTimeout,omitempty"`
WriteTimeout time.Duration `env:"WRITE_TIMEOUT" json:"writeTimeout,omitempty" yaml:"writeTimeout,omitempty"`
IdleTimeout time.Duration `env:"IDLE_TIMEOUT" json:"idleTimeout,omitempty" yaml:"idleTimeout,omitempty"`
Port uint16 `env:"PORT" json:"port" yaml:"port"`
// contains filtered or unexported fields
}
Config describes the settings pertinent to the HTTP serving portion of the service.
func (*Config) ValidateWithContext ¶
ValidateWithContext validates a Config struct.
Neither Port nor StartupDeadline is Required, because zero is meaningful for both: port 0 asks the OS for an ephemeral port, and a zero StartupDeadline means the bind is unbounded. They were Required while nothing called this, which is how the rules came to reject configurations the server accepts.
The timeouts are checked for sign instead: a negative one is always a mistake, and net/http reads it as "no timeout" rather than rejecting it.
type Option ¶
type Option func(*options)
Option configures the server this package constructs. The zero configuration works: an absent logger logs nowhere and an absent tracer provider traces nowhere.
func WithServiceName ¶
WithServiceName names the server's logger and instrumentation scope. It matches the gRPC sibling's option of the same name.
func WithTracerProvider ¶
func WithTracerProvider(tracerProvider tracing.TracerProvider) Option
WithTracerProvider attaches a tracer provider, enabling spans on served requests.
type Server ¶
type Server interface {
// Serve binds the listener and serves until Shutdown is called or the
// context is done. A graceful close reports no error.
Serve(ctx context.Context) error
// Shutdown drains in-flight requests, then flushes and shuts down the
// tracer provider.
Shutdown(ctx context.Context) error
Router() *routing.Router
}
func NewHTTPServer ¶
func NewHTTPServer( ctx context.Context, serverSettings *Config, router *routing.Router, opts ...Option, ) (Server, error)
NewHTTPServer builds a new server instance.
serverSettings may be nil, which is treated as a zero-valued Config. The config is validated: a server that never binds because Port was unset should fail here rather than at the first request that does not arrive.
The service name comes from WithServiceName, not a positional argument, so it sits with the other observability wiring — and matches the gRPC sibling.