API reference
wire
JSON response helpers and value types that keep API bodies byte-compatible with a PHP (WinterCMS/Laravel) backend.
On this page
import "git.golem15.com/golem15/summercms/modules/wire"
Overview#
wire is the lowest layer of the HTTP stack: it decides how a Go value becomes response bytes. Its helpers reproduce what json_encode and Carbon produce in a WinterCMS or Laravel app (unescaped HTML characters, no trailing newline, +00:00 timestamps, nullable booleans, [] rather than null for empty lists), so an endpoint ported from PHP returns the same body its existing clients already parse. surf uses it for the opaque 500 response of its panic recovery, and application handlers use it directly for their JSON responses.
Features#
wire.WriteJSONencodes a value with HTML escaping disabled and without the trailing newlineencoding/jsonadds, then setsContent-Type: application/jsonand the status code. If encoding fails, it writes the opaque 500 body instead of a partial response.wire.WriteOpaque500writes a 500 response with the fixed body{"error":true,"message":"Internal server error"}, which reveals nothing about the failure.wire.Timewrapstime.Timeand always marshals in UTC as2006-01-02T15:04:05+00:00(Carbon's form, never Go'sZ). It unmarshals a timestamp with a numeric offset or an RFC 3339Ztimestamp, and turnsnullinto the zero time.wire.TriBoolmodels a nullable boolean: whenwire.TriBool.Validis false it marshals asnull, otherwise aswire.TriBool.Value.wire.Slicereturns a non-nil empty slice for a nil input, so optional lists marshal as[]instead ofnull.
Usage#
package blog
import (
"net/http"
"time"
"git.golem15.com/golem15/summercms/modules/wire"
)
type postJSON struct {
ID uint `json:"id"`
Title string `json:"title"`
Tags []string `json:"tags"`
Featured wire.TriBool `json:"featured"`
PublishedAt wire.Time `json:"published_at"`
}
func showPost(w http.ResponseWriter, r *http.Request) {
var tags []string // nil when the post has no tags
body := postJSON{
ID: 1,
Title: "Hello & welcome", // "&" stays unescaped
Tags: wire.Slice(tags), // marshals as []
Featured: wire.TriBool{}, // marshals as null
PublishedAt: wire.Time{Time: time.Now()}, // "...+00:00"
}
wire.WriteJSON(w, http.StatusOK, map[string]any{"data": body})
}
API reference#
| Identifier | Description |
|---|---|
wire.WriteJSON |
Writes a JSON body with HTML escaping off and no trailing newline; falls back to the opaque 500 on an encoding error. |
wire.WriteOpaque500 |
Writes the fixed {"error":true,"message":"Internal server error"} 500 response. |
wire.Time |
time.Time wrapper that marshals as UTC +00:00 and reads both +00:00 and Z forms. |
wire.TriBool |
Nullable boolean: wire.TriBool.Valid false marshals null, otherwise wire.TriBool.Value. |
wire.Slice |
Generic helper that turns a nil slice into an empty one so it marshals as []. |
Dependencies#
- SummerCMS modules: none.
- Third-party: none.
- Standard library:
bytes,encoding/json,net/http,time.
Testing#
go test ./modules/wire/...
The tests use net/http/httptest and need no external services.