Documentation
¶
Overview ¶
Package files serves an object bucket over a route prefix.
It exists so that every module that accepts user uploads gets the same three guarantees without rewriting them: the stored type is the one deduced from the bytes, the key is minted by the server, and the size is checked before a single byte of the body is buffered.
Index ¶
Constants ¶
const Action = model.Create
Action is what uploading does: it CREATES an object under a key the server generates. It is not "write" — the action vocabulary is closed CRUD, and an invented verb is a permission nothing enforces.
const ( // DefaultMaxSize is the largest upload accepted unless the caller says otherwise. DefaultMaxSize = 10 << 20 // 10 MiB )
const Resource model.Resource = "files"
Resource is the permission an app must grant to let a caller upload. It is exported because the app is the one that decides WHO holds it: the library states the requirement, the consumer's Authorizer answers it.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Bucket ¶
type Bucket interface {
Put(key string, data []byte, contentType string) error
Get(key string) (data []byte, contentType string, err error)
}
Bucket is the storage this package needs. r2.Bucket satisfies it.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store registers the upload and serve handlers for one bucket under one prefix.
func New ¶
New builds a Store on the safe defaults: raster images only, 10 MiB. prefix must end in "/" — it is matched by prefix, and the key is what hangs off it.
func (*Store) Allow ¶
Allow narrows or widens the accepted types. Never add SVG or HTML: both carry JavaScript and, served from your own domain, execute in your origin.
func (*Store) Mount ¶
Mount registers both routes: uploading requires the files/Create permission, serving is public because an <img src> cannot send headers.
The upload is guarded on purpose. Do NOT make it public to "fix" a 403: a write-open bucket is a spam form. If uploads are rejected, the app has not told the router who the caller is (edge.Config.Authn) or who may write (edge.Config.Authorize).
func (*Store) PerOwner ¶
PerOwner keys the object by its uploader: ONE object per identity, replaced whenever that identity uploads again. The natural shape of an avatar, a profile photo, a signature.
The key is the caller's UserID and nothing else — no extension. The type is NOT lost: it was deduced from the bytes and travels in the object's metadata, which is exactly where serve() already reads it from. An extension would defeat the point: uploading a .png and then a .jpg would produce TWO keys, and the first would be orphaned forever.
It is only reachable on a guarded route (upload already Requires files/Create), so the identity is never empty by construction.