git_pages

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jan 17, 2026 License: 0BSD Imports: 83 Imported by: 0

Documentation

Index

Constants

View Source
const BlobReferencePrefix = "/git/blobs/"
View Source
const HeadersFileName string = "_headers"
View Source
const RedirectsFileName string = "_redirects"

Variables

View Source
var (
	Type_name = map[int32]string{
		0: "InvalidEntry",
		1: "Directory",
		2: "InlineFile",
		3: "ExternalFile",
		4: "Symlink",
	}
	Type_value = map[string]int32{
		"InvalidEntry": 0,
		"Directory":    1,
		"InlineFile":   2,
		"ExternalFile": 3,
		"Symlink":      4,
	}
)

Enum value maps for Type.

View Source
var (
	Transform_name = map[int32]string{
		0: "Identity",
		1: "Zstd",
	}
	Transform_value = map[string]int32{
		"Identity": 0,
		"Zstd":     1,
	}
)

Enum value maps for Transform.

View Source
var (
	AuditEvent_name = map[int32]string{
		0: "InvalidEvent",
		1: "CommitManifest",
		2: "DeleteManifest",
		3: "FreezeDomain",
		4: "UnfreezeDomain",
	}
	AuditEvent_value = map[string]int32{
		"InvalidEvent":   0,
		"CommitManifest": 1,
		"DeleteManifest": 2,
		"FreezeDomain":   3,
		"UnfreezeDomain": 4,
	}
)

Enum value maps for AuditEvent.

View Source
var ErrArchiveTooLarge = errors.New("archive too large")
View Source
var ErrDomainFrozen = errors.New("domain administratively frozen")
View Source
var ErrHeaderNotAllowed = errors.New("custom header not allowed")
View Source
var ErrMalformedPatch = errors.New("malformed patch")
View Source
var ErrManifestTooLarge = errors.New("manifest too large")
View Source
var ErrObjectNotFound = errors.New("not found")
View Source
var ErrPreconditionFailed = errors.New("precondition failed")
View Source
var ErrRepositoryTooLarge = errors.New("repository too large")
View Source
var ErrSiteTooLarge = errors.New("site too large")
View Source
var ErrSymlinkLoop = errors.New("symbolic link loop")
View Source
var ErrWriteConflict = errors.New("write conflict")
View Source
var File_schema_proto protoreflect.FileDescriptor
View Source
var PrincipalKey = principalKey{}

Functions

func AddProblem

func AddProblem(manifest *Manifest, pathName, format string, args ...any) error

func ApplyHeaderRules

func ApplyHeaderRules(manifest *Manifest, url *url.URL) (headers http.Header, err error)

func ApplyTarPatch

func ApplyTarPatch(manifest *Manifest, reader io.Reader, parents CreateParentsMode) error

Mutates `manifest` according to a tar stream and the following rules:

  • A character device with major 0 and minor 0 is a "whiteout marker". When placed at a given path, this path and its entire subtree (if any) are removed from the manifest.
  • When a directory is placed at a given path, this path and its entire subtree (if any) are removed from the manifest and replaced with the contents of the directory.

func AuditEventProcessor

func AuditEventProcessor(command string, args []string) (http.Handler, error)

func AuditRecordJSON

func AuditRecordJSON(record *AuditRecord, scope AuditRecordScope) []byte

func AuthorizeBranch

func AuthorizeBranch(branch string, auth *Authorization) error

The purpose of `allowRepoURLs` is to make sure that only authorized content is deployed to the site despite the fact that the non-shared-secret authorization methods allow anyone to impersonate the legitimate webhook sender. (If switching to another repository URL would be catastrophic, then so would be switching to a different branch.)

func AuthorizeRepository

func AuthorizeRepository(repoURL string, auth *Authorization) error

func CheckForbiddenDomain

func CheckForbiddenDomain(r *http.Request) error

func CollectHeadersFile

func CollectHeadersFile(manifest *Manifest) string

func CollectRedirectsFile

func CollectRedirectsFile(manifest *Manifest) string

func CollectTar

func CollectTar(
	context context.Context, writer io.Writer, manifest *Manifest, metadata ManifestMetadata,
) (
	err error,
)

Inverse of `ExtractTar`.

func CompareManifest

func CompareManifest(left *Manifest, right *Manifest) bool

Returns `true` if `left` and `right` contain the same files with the same types and data.

func CompressFiles

func CompressFiles(ctx context.Context, manifest *Manifest)

Compress contents of inline files.

func DetectContentType

func DetectContentType(manifest *Manifest)

Sniff content type using the same algorithm as `http.ServeContent`.

func EncodeAuditRecord

func EncodeAuditRecord(record *AuditRecord) (data []byte)

func EncodeManifest

func EncodeManifest(manifest *Manifest) (data []byte)

func EnsureLeadingDirectories added in v0.4.0

func EnsureLeadingDirectories(manifest *Manifest)

EnsureLeadingDirectories adds directory entries for any parent directories that are implicitly referenced by files in the manifest but don't have explicit directory entries. (This can be the case if an archive is created via globs rather than including a whole directory.)

func ExpandSymlinks(manifest *Manifest, inPath string) (string, error)

func ExtractAuditRecord

func ExtractAuditRecord(ctx context.Context, id AuditID, record *AuditRecord, dest string) error

This function receives `id` and `record` separately because the record itself may have its ID missing or mismatched. While this is very unlikely, using the actual primary key as the filename is more robust.

func FileLock

func FileLock(file *os.File) error

func FileUnlock

func FileUnlock(file *os.File) error

func FiniObservability

func FiniObservability()

func GetHost

func GetHost(r *http.Request) (string, error)

func GetProblemReport

func GetProblemReport(manifest *Manifest) []string

func GetProjectName

func GetProjectName(r *http.Request) (string, error)

func InitObservability

func InitObservability()

func Is3xxHTTPStatus

func Is3xxHTTPStatus(status int) bool

func IsAllowedCustomHeader

func IsAllowedCustomHeader(header string) bool

func IsManifestEmpty

func IsManifestEmpty(manifest *Manifest) bool

func IsUnauthorized

func IsUnauthorized(err error) bool

func IsValidProjectName added in v0.4.0

func IsValidProjectName(name string) bool

func LintRedirects added in v0.3.0

func LintRedirects(manifest *Manifest)

func Main

func Main()

func ManifestJSON

func ManifestJSON(manifest *Manifest) []byte

func ObserveData

func ObserveData(ctx context.Context, data ...any)

func ObserveError

func ObserveError(err error)

func ObserveFunction

func ObserveFunction(
	ctx context.Context, funcName string, data ...any,
) (
	interface{ Finish() }, context.Context,
)

func ObserveHTTPHandler

func ObserveHTTPHandler(handler http.Handler) http.Handler

func OnReload

func OnReload(handler func())

func PrepareManifest

func PrepareManifest(ctx context.Context, manifest *Manifest) error

Apply post-processing steps to the manifest. At the moment, there isn't a good way to report errors except to log them on the terminal. (Perhaps in the future they could be exposed at `.git-pages/status.txt`?)

func PrintConfigEnvVars

func PrintConfigEnvVars()

func ProcessHeadersFile

func ProcessHeadersFile(manifest *Manifest) error

Parses redirects file and injects rules into the manifest.

func ProcessRedirectsFile

func ProcessRedirectsFile(manifest *Manifest) error

Parses redirects file and injects rules into the manifest.

func ReadAtMost

func ReadAtMost(reader io.Reader, count int64, err error) io.Reader

func RunMigration

func RunMigration(ctx context.Context, name string) error

func ServeCaddy

func ServeCaddy(w http.ResponseWriter, r *http.Request)

func ServePages

func ServePages(w http.ResponseWriter, r *http.Request)

func TraceGarbage added in v0.3.0

func TraceGarbage(ctx context.Context) error

func WaitForInterrupt

func WaitForInterrupt()

func WithPrincipal

func WithPrincipal(ctx context.Context) context.Context

Types

type AuditConfig

type AuditConfig struct {
	// Globally unique machine identifier (0 to 63 inclusive).
	NodeID int `toml:"node-id"`
	// Whether audit reports should be stored whenever an audit event occurs.
	Collect bool `toml:"collect"`
	// If not empty, includes the principal's IP address in audit reports, with the value specifying
	// the source of the IP address. If the value is "X-Forwarded-For", the last item of the
	// corresponding header field (assumed to be comma-separated) is used. If the value is
	// "RemoteAddr", the connecting host's address is used. Any other value is disallowed.
	IncludeIPs string `toml:"include-ip"`
	// Endpoint to notify with a `GET /<notify-url>?<id>` whenever an audit event occurs.
	NotifyURL *URL `toml:"notify-url"`
}

type AuditEvent

type AuditEvent int32
const (
	// Invalid event.
	AuditEvent_InvalidEvent AuditEvent = 0
	// A manifest was committed (a site was created or updated).
	AuditEvent_CommitManifest AuditEvent = 1
	// A manifest was deleted (a site was deleted).
	AuditEvent_DeleteManifest AuditEvent = 2
	// A domain was frozen.
	AuditEvent_FreezeDomain AuditEvent = 3
	// A domain was thawed.
	AuditEvent_UnfreezeDomain AuditEvent = 4
)

func (AuditEvent) Descriptor

func (AuditEvent) Descriptor() protoreflect.EnumDescriptor

func (AuditEvent) Enum

func (x AuditEvent) Enum() *AuditEvent

func (AuditEvent) EnumDescriptor deprecated

func (AuditEvent) EnumDescriptor() ([]byte, []int)

Deprecated: Use AuditEvent.Descriptor instead.

func (AuditEvent) Number

func (x AuditEvent) Number() protoreflect.EnumNumber

func (AuditEvent) String

func (x AuditEvent) String() string

func (AuditEvent) Type

type AuditID

type AuditID int64

func GenerateAuditID

func GenerateAuditID() AuditID

func ParseAuditID

func ParseAuditID(repr string) (AuditID, error)

func (AuditID) CompareTime

func (id AuditID) CompareTime(when time.Time) int

func (AuditID) String

func (id AuditID) String() string

type AuditRecord

type AuditRecord struct {

	// Audit event metadata.
	Id        *int64                 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
	Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp" json:"timestamp,omitempty"`
	Event     *AuditEvent            `protobuf:"varint,3,opt,name=event,enum=AuditEvent" json:"event,omitempty"`
	Principal *Principal             `protobuf:"bytes,4,opt,name=principal" json:"principal,omitempty"`
	// Affected resource.
	Domain  *string `protobuf:"bytes,10,opt,name=domain" json:"domain,omitempty"`
	Project *string `protobuf:"bytes,11,opt,name=project" json:"project,omitempty"` // only for `*Manifest` events
	// Snapshot of site manifest.
	Manifest *Manifest `protobuf:"bytes,12,opt,name=manifest" json:"manifest,omitempty"` // only for `*Manifest` events
	// contains filtered or unexported fields
}

func DecodeAuditRecord

func DecodeAuditRecord(data []byte) (record *AuditRecord, err error)

func (*AuditRecord) DescribePrincipal

func (record *AuditRecord) DescribePrincipal() string

func (*AuditRecord) DescribeResource

func (record *AuditRecord) DescribeResource() string

func (*AuditRecord) Descriptor deprecated

func (*AuditRecord) Descriptor() ([]byte, []int)

Deprecated: Use AuditRecord.ProtoReflect.Descriptor instead.

func (*AuditRecord) GetAuditID

func (record *AuditRecord) GetAuditID() AuditID

func (*AuditRecord) GetDomain

func (x *AuditRecord) GetDomain() string

func (*AuditRecord) GetEvent

func (x *AuditRecord) GetEvent() AuditEvent

func (*AuditRecord) GetId

func (x *AuditRecord) GetId() int64

func (*AuditRecord) GetManifest

func (x *AuditRecord) GetManifest() *Manifest

func (*AuditRecord) GetPrincipal

func (x *AuditRecord) GetPrincipal() *Principal

func (*AuditRecord) GetProject

func (x *AuditRecord) GetProject() string

func (*AuditRecord) GetTimestamp

func (x *AuditRecord) GetTimestamp() *timestamppb.Timestamp

func (*AuditRecord) ProtoMessage

func (*AuditRecord) ProtoMessage()

func (*AuditRecord) ProtoReflect

func (x *AuditRecord) ProtoReflect() protoreflect.Message

func (*AuditRecord) Reset

func (x *AuditRecord) Reset()

func (*AuditRecord) String

func (x *AuditRecord) String() string

type AuditRecordScope

type AuditRecordScope int
const (
	AuditRecordComplete AuditRecordScope = iota
	AuditRecordNoManifest
)

type AuthError

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

func (AuthError) Error

func (e AuthError) Error() string

type Authorization

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

func AuthorizeMetadataRetrieval

func AuthorizeMetadataRetrieval(r *http.Request) (*Authorization, error)

Checks whether an operation that enables enumerating site contents is allowed.

func AuthorizeUpdateFromArchive

func AuthorizeUpdateFromArchive(r *http.Request) (*Authorization, error)

func AuthorizeUpdateFromRepository

func AuthorizeUpdateFromRepository(r *http.Request) (*Authorization, error)

Returns `repoURLs, err` where if `err == nil` then the request is authorized to clone from any repository URL included in `repoURLs` (by case-insensitive comparison), or any URL at all if `repoURLs == nil`.

type Backend

type Backend interface {
	// Returns true if the feature has been enabled for this store, false otherwise.
	HasFeature(ctx context.Context, feature BackendFeature) bool

	// Enables the feature for this store.
	EnableFeature(ctx context.Context, feature BackendFeature) error

	// Retrieve a blob. Returns `reader, size, mtime, err`.
	GetBlob(ctx context.Context, name string) (
		reader io.ReadSeeker, metadata BlobMetadata, err error,
	)

	// Store a blob. If a blob called `name` already exists, this function returns `nil` without
	// regards to the old or new contents. It is expected that blobs are content-addressed, i.e.
	// the `name` contains a cryptographic hash of `data`, but the backend is ignorant of this.
	PutBlob(ctx context.Context, name string, data []byte) error

	// Delete a blob. This is an unconditional operation that can break integrity of manifests.
	DeleteBlob(ctx context.Context, name string) error

	// Iterate through all blobs. Whether blobs that are newly added during iteration will appear
	// in the results is unspecified.
	EnumerateBlobs(ctx context.Context) iter.Seq2[BlobMetadata, error]

	// Retrieve a manifest.
	GetManifest(ctx context.Context, name string, opts GetManifestOptions) (
		manifest *Manifest, metadata ManifestMetadata, err error,
	)

	// Stage a manifest. This operation stores a new version of a manifest, locking any blobs
	// referenced from it in place (for garbage collection purposes) but without any other side
	// effects.
	StageManifest(ctx context.Context, manifest *Manifest) error

	// Whether a compare-and-swap operation on a manifest is truly race-free, or only best-effort
	// atomic with a small but non-zero window where two requests may race where the one committing
	// first will have its update lost. (Plain swap operations are always guaranteed to be atomic.)
	HasAtomicCAS(ctx context.Context) bool

	// Commit a manifest. This is an atomic operation; `GetManifest` calls will return either
	// the old version or the new version of the manifest, never anything else.
	CommitManifest(ctx context.Context, name string, manifest *Manifest, opts ModifyManifestOptions) error

	// Delete a manifest.
	DeleteManifest(ctx context.Context, name string, opts ModifyManifestOptions) error

	// Iterate through all manifests. Whether manifests that are newly added during iteration
	// will appear in the results is unspecified.
	EnumerateManifests(ctx context.Context) iter.Seq2[ManifestMetadata, error]

	// Check whether a domain has any deployments.
	CheckDomain(ctx context.Context, domain string) (found bool, err error)

	// Create a domain. This allows us to start serving content for the domain.
	CreateDomain(ctx context.Context, domain string) error

	// Freeze  a domain. This allows a site to be administratively locked, e.g. if it
	// is discovered serving abusive content.
	FreezeDomain(ctx context.Context, domain string) error

	// Thaw a domain. This removes the previously placed administrative lock (if any).
	UnfreezeDomain(ctx context.Context, domain string) error

	// Append a record to the audit log.
	AppendAuditLog(ctx context.Context, id AuditID, record *AuditRecord) error

	// Retrieve a single record from the audit log.
	QueryAuditLog(ctx context.Context, id AuditID) (record *AuditRecord, err error)

	// Retrieve records from the audit log by time range.
	SearchAuditLog(ctx context.Context, opts SearchAuditLogOptions) iter.Seq2[AuditID, error]
}

func CreateBackend

func CreateBackend(ctx context.Context, config *StorageConfig) (backend Backend, err error)

func NewAuditedBackend

func NewAuditedBackend(backend Backend) Backend

func NewObservedBackend

func NewObservedBackend(backend Backend) Backend

type BackendFeature

type BackendFeature string
const (
	FeatureCheckDomainMarker BackendFeature = "check-domain-marker"
)

type BlobMetadata added in v0.3.0

type BlobMetadata struct {
	Name         string
	Size         int64
	LastModified time.Time
}

type BoundedReader

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

func (*BoundedReader) Read

func (reader *BoundedReader) Read(dest []byte) (count int, err error)

type CacheConfig

type CacheConfig struct {
	MaxSize  datasize.ByteSize `toml:"max-size"`
	MaxAge   Duration          `toml:"max-age"`
	MaxStale Duration          `toml:"max-stale"`
}

type CachedBlob

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

Blobs can be safely cached indefinitely. They only need to be evicted to preserve memory.

func (*CachedBlob) Weight

func (c *CachedBlob) Weight() uint32

type CachedManifest

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

Manifests can only be cached for a short time to avoid serving stale content. Browser page loads cause a large burst of manifest accesses that are essential for serving `304 No Content` responses and these need to be handled very quickly, so both hits and misses are cached.

func (*CachedManifest) Weight

func (c *CachedManifest) Weight() uint32

type Config

type Config struct {
	Insecure      bool                `toml:"-" env:"insecure"`
	Features      []string            `toml:"features"`
	LogFormat     string              `toml:"log-format" default:"text"`
	Server        ServerConfig        `toml:"server"`
	Wildcard      []WildcardConfig    `toml:"wildcard"`
	Fallback      FallbackConfig      `toml:"fallback"`
	Storage       StorageConfig       `toml:"storage"`
	Limits        LimitsConfig        `toml:"limits"`
	Audit         AuditConfig         `toml:"audit"`
	Observability ObservabilityConfig `toml:"observability"`
}

func Configure

func Configure(tomlPath string) (config *Config, err error)

func (*Config) Feature

func (config *Config) Feature(name string) bool

func (*Config) TOML added in v0.3.1

func (config *Config) TOML() string

type CreateParentsMode

type CreateParentsMode int
const (
	RequireParents CreateParentsMode = iota
	CreateParents
)

type Duration

type Duration time.Duration

For an unknown reason, the standard `time.Duration` type doesn't implement the standard `encoding.{TextMarshaler,TextUnmarshaler}` interfaces.

func (*Duration) MarshalText

func (t *Duration) MarshalText() ([]byte, error)

func (Duration) String

func (t Duration) String() string

func (*Duration) UnmarshalText

func (t *Duration) UnmarshalText(data []byte) (err error)

type Entry

type Entry struct {
	Type *Type `protobuf:"varint,1,opt,name=type,enum=Type" json:"type,omitempty"`
	// Only present for `type == InlineFile` and `type == ExternalFile`.
	// For transformed entries, refers to the pre-transformation (decompressed) size; otherwise
	// equal to `compressed_size`.
	OriginalSize *int64 `protobuf:"varint,7,opt,name=original_size,json=originalSize" json:"original_size,omitempty"`
	// Only present for `type == InlineFile` and `type == ExternalFile`.
	// For transformed entries, refers to the post-transformation (compressed) size; otherwise
	// equal to `original_size`.
	CompressedSize *int64 `protobuf:"varint,2,opt,name=compressed_size,json=compressedSize" json:"compressed_size,omitempty"`
	// Meaning depends on `type`:
	//   - If `type == InlineFile`, contains file data.
	//   - If `type == ExternalFile`, contains blob name (an otherwise unspecified
	//     cryptographically secure content hash).
	//   - If `type == Symlink`, contains link target.
	//   - Otherwise not present.
	Data []byte `protobuf:"bytes,3,opt,name=data" json:"data,omitempty"`
	// Only present for `type == InlineFile` and `type == ExternalFile` that
	// have been transformed.
	Transform *Transform `protobuf:"varint,4,opt,name=transform,enum=Transform" json:"transform,omitempty"`
	// Only present for `type == InlineFile` and `type == ExternalFile`.
	// Currently, optional (not present on certain legacy manifests).
	ContentType *string `protobuf:"bytes,5,opt,name=content_type,json=contentType" json:"content_type,omitempty"`
	// May be present for `type == InlineFile` and `type == ExternalFile`.
	// Used to reduce the amount of work being done during git checkouts.
	// The type of hash used is determined by the length:
	//   - 40 bytes: SHA1DC (as hex)
	//   - 64 bytes: SHA256 (as hex)
	GitHash *string `protobuf:"bytes,6,opt,name=git_hash,json=gitHash" json:"git_hash,omitempty"`
	// contains filtered or unexported fields
}

func AddDirectory

func AddDirectory(manifest *Manifest, dirName string) *Entry

func AddFile

func AddFile(manifest *Manifest, fileName string, data []byte) *Entry
func AddSymlink(manifest *Manifest, fileName string, target string) *Entry

func NewManifestEntry

func NewManifestEntry(type_ Type, data []byte) *Entry

func (*Entry) Descriptor deprecated

func (*Entry) Descriptor() ([]byte, []int)

Deprecated: Use Entry.ProtoReflect.Descriptor instead.

func (*Entry) GetCompressedSize

func (x *Entry) GetCompressedSize() int64

func (*Entry) GetContentType

func (x *Entry) GetContentType() string

func (*Entry) GetData

func (x *Entry) GetData() []byte

func (*Entry) GetGitHash

func (x *Entry) GetGitHash() string

func (*Entry) GetOriginalSize

func (x *Entry) GetOriginalSize() int64

func (*Entry) GetTransform

func (x *Entry) GetTransform() Transform

func (*Entry) GetType

func (x *Entry) GetType() Type

func (*Entry) ProtoMessage

func (*Entry) ProtoMessage()

func (*Entry) ProtoReflect

func (x *Entry) ProtoReflect() protoreflect.Message

func (*Entry) Reset

func (x *Entry) Reset()

func (*Entry) String

func (x *Entry) String() string

type FSBackend

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

func NewFSBackend

func NewFSBackend(ctx context.Context, config *FSConfig) (*FSBackend, error)

func (*FSBackend) AppendAuditLog

func (fs *FSBackend) AppendAuditLog(ctx context.Context, id AuditID, record *AuditRecord) error

func (*FSBackend) Backend

func (fs *FSBackend) Backend() Backend

func (*FSBackend) CheckDomain

func (fs *FSBackend) CheckDomain(ctx context.Context, domain string) (bool, error)

func (*FSBackend) CommitManifest

func (fs *FSBackend) CommitManifest(
	ctx context.Context, name string, manifest *Manifest, opts ModifyManifestOptions,
) error

func (*FSBackend) CreateDomain

func (fs *FSBackend) CreateDomain(ctx context.Context, domain string) error

func (*FSBackend) DeleteBlob

func (fs *FSBackend) DeleteBlob(ctx context.Context, name string) error

func (*FSBackend) DeleteManifest

func (fs *FSBackend) DeleteManifest(
	ctx context.Context, name string, opts ModifyManifestOptions,
) error

func (*FSBackend) EnableFeature

func (fs *FSBackend) EnableFeature(ctx context.Context, feature BackendFeature) error

func (*FSBackend) EnumerateBlobs added in v0.3.0

func (fs *FSBackend) EnumerateBlobs(ctx context.Context) iter.Seq2[BlobMetadata, error]

func (*FSBackend) EnumerateManifests added in v0.3.0

func (fs *FSBackend) EnumerateManifests(ctx context.Context) iter.Seq2[ManifestMetadata, error]

func (*FSBackend) FreezeDomain

func (fs *FSBackend) FreezeDomain(ctx context.Context, domain string) error

func (*FSBackend) GetBlob

func (fs *FSBackend) GetBlob(
	ctx context.Context, name string,
) (
	reader io.ReadSeeker, metadata BlobMetadata, err error,
)

func (*FSBackend) GetManifest

func (fs *FSBackend) GetManifest(
	ctx context.Context, name string, opts GetManifestOptions,
) (
	manifest *Manifest, metadata ManifestMetadata, err error,
)

func (*FSBackend) HasAtomicCAS

func (fs *FSBackend) HasAtomicCAS(ctx context.Context) bool

func (*FSBackend) HasFeature

func (fs *FSBackend) HasFeature(ctx context.Context, feature BackendFeature) bool

func (*FSBackend) PutBlob

func (fs *FSBackend) PutBlob(ctx context.Context, name string, data []byte) error

func (*FSBackend) QueryAuditLog

func (fs *FSBackend) QueryAuditLog(ctx context.Context, id AuditID) (*AuditRecord, error)

func (*FSBackend) SearchAuditLog

func (fs *FSBackend) SearchAuditLog(
	ctx context.Context, opts SearchAuditLogOptions,
) iter.Seq2[AuditID, error]

func (*FSBackend) StageManifest

func (fs *FSBackend) StageManifest(ctx context.Context, manifest *Manifest) error

func (*FSBackend) UnfreezeDomain added in v0.3.0

func (fs *FSBackend) UnfreezeDomain(ctx context.Context, domain string) error

type FSConfig

type FSConfig struct {
	Root string `toml:"root"`
}

type FallbackConfig

type FallbackConfig struct {
	ProxyTo  *URL `toml:"proxy-to"`
	Insecure bool `toml:"insecure"`
}

type Flusher

type Flusher interface {
	Flush() error
}

type GetManifestOptions

type GetManifestOptions struct {
	// If true and the manifest is past the cache `MaxAge`, `GetManifest` blocks and returns
	// a fresh object instead of revalidating in background and returning a stale object.
	BypassCache bool
}

type HTTPContentTypes added in v0.3.0

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

func ParseAcceptHeader added in v0.3.0

func ParseAcceptHeader(headerValue string) (result HTTPContentTypes)

func (*HTTPContentTypes) Negotiate added in v0.3.0

func (e *HTTPContentTypes) Negotiate(offers ...string) string

type HTTPEncodings added in v0.3.0

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

func ParseAcceptEncodingHeader added in v0.3.0

func ParseAcceptEncodingHeader(headerValue string) (result HTTPEncodings)

func (*HTTPEncodings) Negotiate added in v0.3.0

func (e *HTTPEncodings) Negotiate(offers ...string) string

Negotiate returns the most preferred encoding that is acceptable by the client, or an empty string if no encodings are acceptable.

type Header struct {
	Name   *string  `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
	Values []string `protobuf:"bytes,2,rep,name=values" json:"values,omitempty"`
	// contains filtered or unexported fields
}

See https://docs.netlify.com/manage/routing/headers/ for details.

func (*Header) Descriptor deprecated

func (*Header) Descriptor() ([]byte, []int)

Deprecated: Use Header.ProtoReflect.Descriptor instead.

func (*Header) GetName

func (x *Header) GetName() string

func (*Header) GetValues

func (x *Header) GetValues() []string

func (*Header) ProtoMessage

func (*Header) ProtoMessage()

func (*Header) ProtoReflect

func (x *Header) ProtoReflect() protoreflect.Message

func (*Header) Reset

func (x *Header) Reset()

func (*Header) String

func (x *Header) String() string

type HeaderRule

type HeaderRule struct {
	Path      *string   `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"`
	HeaderMap []*Header `protobuf:"bytes,2,rep,name=header_map,json=headerMap" json:"header_map,omitempty"`
	// contains filtered or unexported fields
}

func (*HeaderRule) Descriptor deprecated

func (*HeaderRule) Descriptor() ([]byte, []int)

Deprecated: Use HeaderRule.ProtoReflect.Descriptor instead.

func (*HeaderRule) GetHeaderMap

func (x *HeaderRule) GetHeaderMap() []*Header

func (*HeaderRule) GetPath

func (x *HeaderRule) GetPath() string

func (*HeaderRule) ProtoMessage

func (*HeaderRule) ProtoMessage()

func (*HeaderRule) ProtoReflect

func (x *HeaderRule) ProtoReflect() protoreflect.Message

func (*HeaderRule) Reset

func (x *HeaderRule) Reset()

func (*HeaderRule) String

func (x *HeaderRule) String() string

type LimitsConfig

type LimitsConfig struct {
	// Maximum size of a single published site. Also used to limit the size of archive
	// uploads and other similar overconsumption conditions.
	MaxSiteSize datasize.ByteSize `toml:"max-site-size" default:"128M"`
	// Maximum size of a single site manifest, computed over its binary Protobuf
	// serialization.
	MaxManifestSize datasize.ByteSize `toml:"max-manifest-size" default:"1M"`
	// Maximum size of a file that will still be inlined into the site manifest.
	MaxInlineFileSize datasize.ByteSize `toml:"max-inline-file-size" default:"256B"`
	// Maximum size of a Git object that will be cached in memory during Git operations.
	GitLargeObjectThreshold datasize.ByteSize `toml:"git-large-object-threshold" default:"1M"`
	// Maximum number of symbolic link traversals before the path is considered unreachable.
	MaxSymlinkDepth uint `toml:"max-symlink-depth" default:"16"`
	// Maximum time that an update operation (PUT or POST request) could take before being
	// interrupted.
	UpdateTimeout Duration `toml:"update-timeout" default:"60s"`
	// Soft limit on Go heap size, expressed as a fraction of total available RAM.
	MaxHeapSizeRatio float64 `toml:"max-heap-size-ratio" default:"0.5"`
	// List of domains unconditionally forbidden for uploads.
	ForbiddenDomains []string `toml:"forbidden-domains" default:"[]"`
	// List of allowed repository URL prefixes. Setting this option prohibits uploading archives.
	AllowedRepositoryURLPrefixes []string `toml:"allowed-repository-url-prefixes" default:"[]"`
	// List of allowed custom headers. Header name must be in the MIME canonical form,
	// e.g. `Foo-Bar`. Setting this option permits including this custom header in `_headers`,
	// unless it is fundamentally unsafe.
	AllowedCustomHeaders []string `toml:"allowed-custom-headers" default:"[\"X-Clacks-Overhead\"]"`
}

type Manifest

type Manifest struct {

	// Source metadata.
	RepoUrl *string `protobuf:"bytes,1,opt,name=repo_url,json=repoUrl" json:"repo_url,omitempty"`
	Branch  *string `protobuf:"bytes,2,opt,name=branch" json:"branch,omitempty"`
	Commit  *string `protobuf:"bytes,3,opt,name=commit" json:"commit,omitempty"`
	// Site contents.
	Contents       map[string]*Entry ``                                                                                                  /* 136-byte string literal not displayed */
	OriginalSize   *int64            `protobuf:"varint,10,opt,name=original_size,json=originalSize" json:"original_size,omitempty"`      // sum of each `entry.original_size`
	CompressedSize *int64            `protobuf:"varint,5,opt,name=compressed_size,json=compressedSize" json:"compressed_size,omitempty"` // sum of each `entry.compressed_size`
	StoredSize     *int64            `protobuf:"varint,8,opt,name=stored_size,json=storedSize" json:"stored_size,omitempty"`             // sum of deduplicated `entry.compressed_size` for external files only
	// Netlify-style `_redirects` and `_headers` rules.
	Redirects []*RedirectRule `protobuf:"bytes,6,rep,name=redirects" json:"redirects,omitempty"`
	Headers   []*HeaderRule   `protobuf:"bytes,9,rep,name=headers" json:"headers,omitempty"`
	// Diagnostics for non-fatal errors.
	Problems []*Problem `protobuf:"bytes,7,rep,name=problems" json:"problems,omitempty"`
	// contains filtered or unexported fields
}

func DecodeManifest

func DecodeManifest(data []byte) (manifest *Manifest, err error)

func ExtractGzip

func ExtractGzip(
	ctx context.Context, reader io.Reader,
	next func(context.Context, io.Reader) (*Manifest, error),
) (*Manifest, error)

func ExtractTar

func ExtractTar(ctx context.Context, reader io.Reader, oldManifest *Manifest) (*Manifest, error)

func ExtractZip

func ExtractZip(ctx context.Context, reader io.Reader, oldManifest *Manifest) (*Manifest, error)

func ExtractZstd

func ExtractZstd(
	ctx context.Context, reader io.Reader,
	next func(context.Context, io.Reader) (*Manifest, error),
) (*Manifest, error)

func FetchRepository

func FetchRepository(
	ctx context.Context, repoURL string, branch string, oldManifest *Manifest,
) (
	*Manifest, error,
)

func NewManifest

func NewManifest() *Manifest

func StoreManifest

func StoreManifest(
	ctx context.Context, name string, manifest *Manifest, opts ModifyManifestOptions,
) (*Manifest, error)

Uploads inline file data over certain size to the storage backend. Returns a copy of the manifest updated to refer to an external content-addressable store.

func (*Manifest) Descriptor deprecated

func (*Manifest) Descriptor() ([]byte, []int)

Deprecated: Use Manifest.ProtoReflect.Descriptor instead.

func (*Manifest) GetBranch

func (x *Manifest) GetBranch() string

func (*Manifest) GetCommit

func (x *Manifest) GetCommit() string

func (*Manifest) GetCompressedSize

func (x *Manifest) GetCompressedSize() int64

func (*Manifest) GetContents

func (x *Manifest) GetContents() map[string]*Entry

func (*Manifest) GetHeaders

func (x *Manifest) GetHeaders() []*HeaderRule

func (*Manifest) GetOriginalSize

func (x *Manifest) GetOriginalSize() int64

func (*Manifest) GetProblems

func (x *Manifest) GetProblems() []*Problem

func (*Manifest) GetRedirects

func (x *Manifest) GetRedirects() []*RedirectRule

func (*Manifest) GetRepoUrl

func (x *Manifest) GetRepoUrl() string

func (*Manifest) GetStoredSize

func (x *Manifest) GetStoredSize() int64

func (*Manifest) ProtoMessage

func (*Manifest) ProtoMessage()

func (*Manifest) ProtoReflect

func (x *Manifest) ProtoReflect() protoreflect.Message

func (*Manifest) Reset

func (x *Manifest) Reset()

func (*Manifest) String

func (x *Manifest) String() string

type ManifestMetadata

type ManifestMetadata struct {
	Name         string
	Size         int64
	LastModified time.Time
	ETag         string
}

type ModifyManifestOptions

type ModifyManifestOptions struct {
	// If non-zero, the request will only succeed if the manifest hasn't been changed since
	// the given time. Whether this is racy or not is can be determined via `HasAtomicCAS()`.
	IfUnmodifiedSince time.Time
	// If non-empty, the request will only succeed if the manifest hasn't changed from
	// the state corresponding to the ETag. Whether this is racy or not is can be determined
	// via `HasAtomicCAS()`.
	IfMatch string
}

type ObservabilityConfig

type ObservabilityConfig struct {
	// Minimum duration for an HTTP request transaction to be unconditionally sampled.
	SlowResponseThreshold Duration `toml:"slow-response-threshold" default:"500ms"`
}

type Principal

type Principal struct {
	IpAddress *string `protobuf:"bytes,1,opt,name=ip_address,json=ipAddress" json:"ip_address,omitempty"`
	CliAdmin  *bool   `protobuf:"varint,2,opt,name=cli_admin,json=cliAdmin" json:"cli_admin,omitempty"`
	// contains filtered or unexported fields
}

func GetPrincipal

func GetPrincipal(ctx context.Context) *Principal

func (*Principal) Descriptor deprecated

func (*Principal) Descriptor() ([]byte, []int)

Deprecated: Use Principal.ProtoReflect.Descriptor instead.

func (*Principal) GetCliAdmin

func (x *Principal) GetCliAdmin() bool

func (*Principal) GetIpAddress

func (x *Principal) GetIpAddress() string

func (*Principal) ProtoMessage

func (*Principal) ProtoMessage()

func (*Principal) ProtoReflect

func (x *Principal) ProtoReflect() protoreflect.Message

func (*Principal) Reset

func (x *Principal) Reset()

func (*Principal) String

func (x *Principal) String() string

type Problem

type Problem struct {
	Path  *string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"`
	Cause *string `protobuf:"bytes,2,opt,name=cause" json:"cause,omitempty"`
	// contains filtered or unexported fields
}

func (*Problem) Descriptor deprecated

func (*Problem) Descriptor() ([]byte, []int)

Deprecated: Use Problem.ProtoReflect.Descriptor instead.

func (*Problem) GetCause

func (x *Problem) GetCause() string

func (*Problem) GetPath

func (x *Problem) GetPath() string

func (*Problem) ProtoMessage

func (*Problem) ProtoMessage()

func (*Problem) ProtoReflect

func (x *Problem) ProtoReflect() protoreflect.Message

func (*Problem) Reset

func (x *Problem) Reset()

func (*Problem) String

func (x *Problem) String() string

type RedirectKind

type RedirectKind int
const (
	RedirectAny RedirectKind = iota
	RedirectNormal
	RedirectForce
)

type RedirectRule

type RedirectRule struct {
	From   *string `protobuf:"bytes,1,opt,name=from" json:"from,omitempty"`
	To     *string `protobuf:"bytes,2,opt,name=to" json:"to,omitempty"`
	Status *uint32 `protobuf:"varint,3,opt,name=status" json:"status,omitempty"`
	Force  *bool   `protobuf:"varint,4,opt,name=force" json:"force,omitempty"`
	// contains filtered or unexported fields
}

See https://docs.netlify.com/manage/routing/redirects/overview/ for details. Only a subset of the Netlify specification is representable here.

func ApplyRedirectRules

func ApplyRedirectRules(
	manifest *Manifest, fromURL *url.URL, kind RedirectKind,
) (
	rule *RedirectRule, toURL *url.URL, status int,
)

func (*RedirectRule) Descriptor deprecated

func (*RedirectRule) Descriptor() ([]byte, []int)

Deprecated: Use RedirectRule.ProtoReflect.Descriptor instead.

func (*RedirectRule) GetForce

func (x *RedirectRule) GetForce() bool

func (*RedirectRule) GetFrom

func (x *RedirectRule) GetFrom() string

func (*RedirectRule) GetStatus

func (x *RedirectRule) GetStatus() uint32

func (*RedirectRule) GetTo

func (x *RedirectRule) GetTo() string

func (*RedirectRule) ProtoMessage

func (*RedirectRule) ProtoMessage()

func (*RedirectRule) ProtoReflect

func (x *RedirectRule) ProtoReflect() protoreflect.Message

func (*RedirectRule) Reset

func (x *RedirectRule) Reset()

func (*RedirectRule) String

func (x *RedirectRule) String() string

type S3Backend

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

func NewS3Backend

func NewS3Backend(ctx context.Context, config *S3Config) (*S3Backend, error)

func (*S3Backend) AppendAuditLog

func (s3 *S3Backend) AppendAuditLog(ctx context.Context, id AuditID, record *AuditRecord) error

func (*S3Backend) Backend

func (s3 *S3Backend) Backend() Backend

func (*S3Backend) CheckDomain

func (s3 *S3Backend) CheckDomain(ctx context.Context, domain string) (exists bool, err error)

func (*S3Backend) CommitManifest

func (s3 *S3Backend) CommitManifest(
	ctx context.Context, name string, manifest *Manifest, opts ModifyManifestOptions,
) error

func (*S3Backend) CreateDomain

func (s3 *S3Backend) CreateDomain(ctx context.Context, domain string) error

func (*S3Backend) DeleteBlob

func (s3 *S3Backend) DeleteBlob(ctx context.Context, name string) error

func (*S3Backend) DeleteManifest

func (s3 *S3Backend) DeleteManifest(
	ctx context.Context, name string, opts ModifyManifestOptions,
) error

func (*S3Backend) EnableFeature

func (s3 *S3Backend) EnableFeature(ctx context.Context, feature BackendFeature) error

func (*S3Backend) EnumerateBlobs added in v0.3.0

func (s3 *S3Backend) EnumerateBlobs(ctx context.Context) iter.Seq2[BlobMetadata, error]

func (*S3Backend) EnumerateManifests added in v0.3.0

func (s3 *S3Backend) EnumerateManifests(ctx context.Context) iter.Seq2[ManifestMetadata, error]

func (*S3Backend) FreezeDomain

func (s3 *S3Backend) FreezeDomain(ctx context.Context, domain string) error

func (*S3Backend) GetBlob

func (s3 *S3Backend) GetBlob(
	ctx context.Context, name string,
) (
	reader io.ReadSeeker, metadata BlobMetadata, err error,
)

func (*S3Backend) GetManifest

func (s3 *S3Backend) GetManifest(
	ctx context.Context, name string, opts GetManifestOptions,
) (
	manifest *Manifest, metadata ManifestMetadata, err error,
)

func (*S3Backend) HasAtomicCAS

func (s3 *S3Backend) HasAtomicCAS(ctx context.Context) bool

func (*S3Backend) HasFeature

func (s3 *S3Backend) HasFeature(ctx context.Context, feature BackendFeature) bool

func (*S3Backend) PutBlob

func (s3 *S3Backend) PutBlob(ctx context.Context, name string, data []byte) error

func (*S3Backend) QueryAuditLog

func (s3 *S3Backend) QueryAuditLog(ctx context.Context, id AuditID) (*AuditRecord, error)

func (*S3Backend) SearchAuditLog

func (s3 *S3Backend) SearchAuditLog(
	ctx context.Context, opts SearchAuditLogOptions,
) iter.Seq2[AuditID, error]

func (*S3Backend) StageManifest

func (s3 *S3Backend) StageManifest(ctx context.Context, manifest *Manifest) error

func (*S3Backend) UnfreezeDomain added in v0.3.0

func (s3 *S3Backend) UnfreezeDomain(ctx context.Context, domain string) error

type S3Config

type S3Config struct {
	Endpoint        string      `toml:"endpoint"`
	Insecure        bool        `toml:"insecure"`
	AccessKeyID     string      `toml:"access-key-id"`
	SecretAccessKey string      `toml:"secret-access-key"`
	Region          string      `toml:"region"`
	Bucket          string      `toml:"bucket"`
	BlobCache       CacheConfig `toml:"blob-cache" default:"{\"MaxSize\":\"256MB\"}"`
	SiteCache       CacheConfig `toml:"site-cache" default:"{\"MaxAge\":\"60s\",\"MaxStale\":\"1h\",\"MaxSize\":\"16MB\"}"`
}

type SearchAuditLogOptions

type SearchAuditLogOptions struct {
	// Inclusive lower bound on returned audit records, per their Snowflake ID (which may differ
	// slightly from the embedded timestamp). If zero, audit records are returned since beginning
	// of time.
	Since time.Time
	// Inclusive upper bound on returned audit records, per their Snowflake ID (which may differ
	// slightly from the embedded timestamp). If zero, audit records are returned until the end
	// of time.
	Until time.Time
}

type SearchAuditLogResult

type SearchAuditLogResult struct {
	ID  AuditID
	Err error
}

type ServerConfig

type ServerConfig struct {
	Pages   string `toml:"pages" default:"tcp/localhost:3000"`
	Caddy   string `toml:"caddy" default:"tcp/localhost:3001"`
	Metrics string `toml:"metrics" default:"tcp/localhost:3002"`
}

type StorageConfig

type StorageConfig struct {
	Type string   `toml:"type" default:"fs"`
	FS   FSConfig `toml:"fs"  default:"{\"Root\":\"./data\"}"`
	S3   S3Config `toml:"s3"`
}

type Transform

type Transform int32

Transformation names should match HTTP `Accept-Encoding:` header.

const (
	// No transformation.
	Transform_Identity Transform = 0
	// Zstandard compression.
	Transform_Zstd Transform = 1
)

func (Transform) Descriptor

func (Transform) Descriptor() protoreflect.EnumDescriptor

func (Transform) Enum

func (x Transform) Enum() *Transform

func (Transform) EnumDescriptor deprecated

func (Transform) EnumDescriptor() ([]byte, []int)

Deprecated: Use Transform.Descriptor instead.

func (Transform) Number

func (x Transform) Number() protoreflect.EnumNumber

func (Transform) String

func (x Transform) String() string

func (Transform) Type

type Type

type Type int32
const (
	// Invalid entry.
	Type_InvalidEntry Type = 0
	// Directory.
	Type_Directory Type = 1
	// Inline file. `Blob.Data` contains file contents.
	Type_InlineFile Type = 2
	// External file. `Blob.Data` contains object reference.
	Type_ExternalFile Type = 3
	// Symlink. `Blob.Data` contains relative path.
	Type_Symlink Type = 4
)

func (Type) Descriptor

func (Type) Descriptor() protoreflect.EnumDescriptor

func (Type) Enum

func (x Type) Enum() *Type

func (Type) EnumDescriptor deprecated

func (Type) EnumDescriptor() ([]byte, []int)

Deprecated: Use Type.Descriptor instead.

func (Type) Number

func (x Type) Number() protoreflect.EnumNumber

func (Type) String

func (x Type) String() string

func (Type) Type

func (Type) Type() protoreflect.EnumType

type URL

type URL struct {
	url.URL
}

For a known but upsetting reason, the standard `url.URL` type doesn't implement the standard `encoding.{TextMarshaler,TextUnmarshaler}` interfaces.

func (*URL) MarshalText

func (t *URL) MarshalText() ([]byte, error)

func (*URL) String

func (t *URL) String() string

func (*URL) UnmarshalText

func (t *URL) UnmarshalText(data []byte) (err error)

type UnresolvedRefError added in v0.3.0

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

func (UnresolvedRefError) Error added in v0.3.0

func (err UnresolvedRefError) Error() string

type UpdateOutcome

type UpdateOutcome int
const (
	UpdateError UpdateOutcome = iota
	UpdateTimeout
	UpdateCreated
	UpdateReplaced
	UpdateDeleted
	UpdateNoChange
)

type UpdateResult

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

func PartialUpdateFromArchive

func PartialUpdateFromArchive(
	ctx context.Context,
	webRoot string,
	contentType string,
	reader io.Reader,
	parents CreateParentsMode,
) (result UpdateResult)

func Update

func Update(
	ctx context.Context, webRoot string, oldManifest, newManifest *Manifest,
	opts ModifyManifestOptions,
) UpdateResult

func UpdateFromArchive

func UpdateFromArchive(
	ctx context.Context,
	webRoot string,
	contentType string,
	reader io.Reader,
) (result UpdateResult)

func UpdateFromRepository

func UpdateFromRepository(
	ctx context.Context,
	webRoot string,
	repoURL string,
	branch string,
) (result UpdateResult)

type WildcardConfig

type WildcardConfig struct {
	Domain          string   `toml:"domain"`
	CloneURL        string   `toml:"clone-url"` // URL template, not an exact URL
	IndexRepos      []string `toml:"index-repos" default:"[]"`
	IndexRepoBranch string   `toml:"index-repo-branch" default:"pages"`
	Authorization   string   `toml:"authorization"`
}

type WildcardPattern

type WildcardPattern struct {
	Domain        []string
	CloneURL      *fasttemplate.Template
	IndexRepos    []*fasttemplate.Template
	IndexBranch   string
	Authorization bool
}

func TranslateWildcards

func TranslateWildcards(configs []WildcardConfig) ([]*WildcardPattern, error)

func (*WildcardPattern) ApplyTemplate

func (pattern *WildcardPattern) ApplyTemplate(userName string, projectName string) ([]string, string)

func (*WildcardPattern) GetHost

func (pattern *WildcardPattern) GetHost() string

func (*WildcardPattern) Matches

func (pattern *WildcardPattern) Matches(host string) (string, bool)

Returns `subdomain, found` where if `found == true`, `subdomain` contains the part of `host` corresponding to the * in the domain pattern.

Jump to

Keyboard shortcuts

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