71 lines
2.8 KiB
Markdown
71 lines
2.8 KiB
Markdown
# towel
|
|
|
|
Request-scoped actor, organization, collection and locale values carried through `context.Context`.
|
|
|
|
`import "git.golem15.com/golem15/summercms/modules/towel"`
|
|
|
|
## Overview
|
|
|
|
`towel` replaces the request-global state that WinterCMS reads through facades (the current locale, the acting user) with explicit values on the request context. Middleware stores a value once, and any code further down the call chain that receives the context reads it back without a global lookup. [surf](../surf/README.md) sets the locale from `Accept-Language` (or the signed-in user's preferred locale) and the organization for every request, [phrasebook](../phrasebook/README.md) reads the locale when it translates, and [cabana](../cabana/README.md) sets it while localizing admin schemas.
|
|
|
|
## Features
|
|
|
|
- Four independent string values, each with a setter and a getter: actor (`towel.WithActor`, `towel.Actor`), organization (`towel.WithOrganization`, `towel.Organization`), collection (`towel.WithCollection`, `towel.Collection`) and locale (`towel.WithLocale`, `towel.Locale`).
|
|
- Unexported context key types, so no other package can read or overwrite the values by accident.
|
|
- Getters return `(value, ok)`: a value that was set to an empty string is distinguishable from one that was never set.
|
|
- Nil-safe: a setter given a nil context starts from `context.Background()`, and a getter given a nil context reports `false`.
|
|
|
|
## Usage
|
|
|
|
```go
|
|
package blog
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/towel"
|
|
)
|
|
|
|
// withAcmeScope tags every request with the organization and collection it serves.
|
|
func withAcmeScope(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := towel.WithOrganization(r.Context(), "acme")
|
|
ctx = towel.WithCollection(ctx, "blog")
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
|
|
func listPosts(w http.ResponseWriter, r *http.Request) {
|
|
org, _ := towel.Organization(r.Context())
|
|
locale, ok := towel.Locale(r.Context())
|
|
if !ok {
|
|
locale = "en"
|
|
}
|
|
fmt.Fprintf(w, "posts for %s in %s\n", org, locale)
|
|
}
|
|
```
|
|
|
|
## API reference
|
|
|
|
| Identifier | Description |
|
|
|------------|-------------|
|
|
| `towel.WithActor` / `towel.Actor` | Store and read the acting user or client identifier. |
|
|
| `towel.WithOrganization` / `towel.Organization` | Store and read the organization (tenant) the request belongs to. |
|
|
| `towel.WithCollection` / `towel.Collection` | Store and read the collection the request operates on. |
|
|
| `towel.WithLocale` / `towel.Locale` | Store and read the locale used for translations and localized responses. |
|
|
|
|
## Dependencies
|
|
|
|
- SummerCMS modules: none.
|
|
- Third-party: none.
|
|
- Standard library: `context`.
|
|
|
|
## Testing
|
|
|
|
```sh
|
|
go test ./modules/towel/...
|
|
```
|
|
|
|
The tests exercise plain contexts and need no external services.
|