hostsharing

package
v1.10.0 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 18 Imported by: 1

Documentation

Overview

Package hostsharing provides utilities for applications running in Hostsharing environments.

It offers functionality for:

  • Service name detection from environment variables or executable paths
  • Parsing domain and user information from filesystem paths
  • HTTP server configuration for both standard HTTP and FastCGI protocols
  • Configuration file loading with support for domain-specific and user home directories
  • Structured logging with request context tracking

The package is designed to integrate with Hostsharing's directory structure where applications are organized as: /home/pacs/{pac}/users/{user}/doms/{domain}

Index

Constants

This section is empty.

Variables

View Source
var ErrNoFcgiEnvironment = fmt.Errorf("no fcgi environment dedected")

ErrNoFcgiEnvironment indicates that the FastCGI environment was not detected.

View Source
var ErrShortPath = fmt.Errorf("cannot detect PAC/user/domain from path")

ErrShortPath is returned when a path lacks enough components to identify a PAC, user, and domain (requires at least 7 path segments for domains, 5 for users, or 3 for PAC-only paths).

Functions

func Base64StringToBytesHookFunc added in v1.10.0

func Base64StringToBytesHookFunc(encs ...*base64.Encoding) mapstructure.DecodeHookFuncType

Base64StringToBytesHookFunc returns a mapstructure decode hook that turns string fields into []byte by trying each encoding in order. The first encoding that decodes the string wins; if none decode it, the string is returned unchanged. Pass one encoding to accept a single alphabet, several to accept a fallback chain (for example StdEncoding then URLEncoding). Padding rules are set on each encoding — use RawStdEncoding, RawURLEncoding, or Encoding.WithPadding for unpadded or custom-padded input.

func DomainByExecutable added in v1.9.0

func DomainByExecutable() (*domain, error)

DomainByExecutable returns the domain parsed from the current executable's directory path.

Resolution order:

  1. If CONFIG_BASE_PATH is set, parse it as-is; on ErrShortPath, parse its parent directory. This lets local dev point to a binary (…/api.fcgi) or directory (…/doms/example.com).
  2. Otherwise, parse the executable's directory.

Returns ErrShortPath if no source has enough path components for PAC/user/domain. If CONFIG_BASE_PATH is set but invalid, ErrShortPath propagates to signal the error.

func DomainByWorkingDir deprecated

func DomainByWorkingDir() (*domain, error)

DomainByWorkingDir returns the domain parsed from the current working directory. Returns ErrShortPath if the path lacks enough components to identify PAC, user, and domain.

Deprecated: Use DomainByExecutable. It resists startup `chdir` and is used internally by hostsharing.ReadInConfig and the database package. Will be removed in v2.

func IsFCGI

func IsFCGI() bool

IsFCGI checks if the current executable is running in a FastCGI environment by examining the executable path for a "fastcgi" directory component.

func ListenAndServe

func ListenAndServe(handler http.Handler) error

ListenAndServe starts an HTTP server using either FastCGI or standard HTTP, depending on the environment.

It first checks for the FCGI_LISTEN environment variable. If set, it uses FastCGI with the specified address. Otherwise, it falls back to the existing IsFCGI() logic. If neither condition is met, it starts a standard HTTP server on the default port.

Example:

// Caddyfile configuration:
// {
//     auto_https off
//     http_port 1313
//     admin off
// }
// localhost:1313 {
//     root * public
//     file_server
//     reverse_proxy /api/* :9000 {
//         transport fastcgi
//     }
// }
// Set FCGI_LISTEN=:9000 in your environment to enable FastCGI mode.

Example usage:

r := http.NewServeMux()
r.HandleFunc("/api/hello", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, FastCGI!")
})
if err := hostsharing.ListenAndServe(r); err != nil {
    log.Fatalf("Server failed: %v", err)
}

func LogError added in v1.3.0

func LogError(ctx context.Context, format string, args ...any)

LogError logs an error-level message with the request context. If a request ID is present in the context, it is included in the log record.

func LogInfo added in v1.2.0

func LogInfo(ctx context.Context, format string, args ...any)

LogInfo logs an information-level message with the request context. If a request ID is present in the context, it is included in the log record.

func LogWarn added in v1.3.0

func LogWarn(ctx context.Context, format string, args ...any)

LogWarn logs a warning-level message with the request context. If a request ID is present in the context, it is included in the log record.

func ParseDomain

func ParseDomain(p string) (*domain, error)

func ParseUser

func ParseUser(p string) (*user, error)

func ReadInConfig

func ReadInConfig(rawVal any, app_name string, fs ...mapstructure.DecodeHookFunc) error

ReadInConfig reads and unmarshals configuration from a file into the provided value. It attempts to load configuration from a local file first, then falls back to searching in domain-specific and home directories. The function supports custom decode hooks for type conversion during unmarshaling.

Parameters:

  • rawVal: A pointer to a struct where the unmarshaled configuration will be stored.
  • app_name: The application name used to construct config file paths. If empty, it will be determined automatically via ServiceName(). Config files are expected to be named as ".<app_name>.conf".
  • fs: Optional variadic mapstructure.DecodeHookFunc functions for custom type conversion during unmarshaling. If none are provided, default hooks are applied: Base64StringToBytesHookFunc(base64.StdEncoding, base64.URLEncoding), StringToTimeDurationHookFunc(), and StringToSliceHookFunc with "," delimiter.

Returns:

  • error: Returns nil on success, or an error describing what went wrong during config file reading or unmarshaling.

The function searches for config in the following order:

  1. Local file: .<app_name>.conf
  2. Domain-specific directory: /home/pacs/xyz00/users/foobar/doms/example.com/etc/{app_name}/ (user must create config files under this directory, e.g. /home/pacs/xyz00/users/foobar/doms/example.com/etc/api/config)
  3. Home directory: $HOME/.<app_name>/ (user must create config files under this directory)

Domain resolution uses DomainByExecutable, which first honors the CONFIG_BASE_PATH environment variable and falls back to the running executable's directory. Setting CONFIG_BASE_PATH lets local development simulate a Hostsharing layout without a real /home/pacs tree.

func RequestLogger

func RequestLogger() func(next http.Handler) http.Handler

RequestLogger returns an HTTP middleware that logs requests using structured logging. It sets up a JSON logger configured for Google Cloud Logging schema, and logs request/response details including optional requestID from the request context. Certain static asset types (css, js, fonts, etc.) are excluded from logging.

func ServiceName added in v1.6.0

func ServiceName() (string, error)

ServiceName returns the name of the service by checking the SERVICE_NAME environment variable first, and falling back to the executable name if the variable is not set. The ".fcgi" suffix is trimmed from the executable name if present.

It returns an error if neither the environment variable is set nor the executable path can be determined, or if the resulting name is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

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