mirror of
https://github.com/hanzoai/team-go.git
synced 2026-10-30 20:22:42 +00:00
The Go transactor and account service for Hanzo Team. History starts here. The previous 107 commits carried the fork's origin in their messages and their tree, and none of it described this code: the Go under pkg/transactor is Hanzo's own work implementing a wire protocol, not a port of anyone's implementation. pkg/transactor/model.json remains, and remains attributed. It is a compiled platform model this transactor loads through go:embed, governed by EPL-2.0 and named in NOTICE. Removing it is a replacement project -- a new compiler and a move off the protocol -- not a deletion.
66 lines
2.3 KiB
Go
66 lines
2.3 KiB
Go
// Package files exposes /v1/files/{collection}/{recordId}/{filename}
|
|
// as a same-origin alias for the Base file API.
|
|
//
|
|
// Base mounts the file API at ${BASE_API_PREFIX}/files/{collection}/...
|
|
// (default /v1/base/files/...). the platform clients and first-party UIs both
|
|
// prefer the shorter /v1/files/... shape and shouldn't need to know
|
|
// the Base prefix exists. We solve that with a 307 Temporary Redirect:
|
|
//
|
|
// - 307 preserves the request method and body (we don't actually need
|
|
// either for downloads, but it costs nothing and keeps the alias
|
|
// useful for future write endpoints).
|
|
// - The query string (including Base's signed ?token=...) is carried
|
|
// verbatim — match Base's signed-URL behavior 1:1.
|
|
// - It's a single redirect, no proxy hop, no header laundering — the
|
|
// browser fetches Base's CDN-cacheable URL directly.
|
|
//
|
|
// We deliberately do NOT reverse-proxy: the file handler already
|
|
// streams from filesystem.System through the Base router, and copying
|
|
// the bytes through another goroutine would just halve throughput
|
|
// while breaking range requests + ETag negotiation.
|
|
package files
|
|
|
|
import (
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hanzoai/base/core"
|
|
"github.com/hanzoai/base/tools/hook"
|
|
)
|
|
|
|
// Register binds /v1/files/{path...} on the Base app.
|
|
func Register(app core.App) {
|
|
app.OnServe().Bind(&hook.Handler[*core.ServeEvent]{
|
|
Func: func(e *core.ServeEvent) error {
|
|
e.Router.GET("/v1/files/{path...}", redirect)
|
|
e.Router.POST("/v1/files/token", redirect) // token-mint passthrough
|
|
return e.Next()
|
|
},
|
|
})
|
|
}
|
|
|
|
// basePrefix mirrors apis.NewRouter's BASE_API_PREFIX lookup so
|
|
// /v1/files/x routes to whatever prefix Base is actually serving.
|
|
func basePrefix() string {
|
|
if v := os.Getenv("BASE_API_PREFIX"); v != "" {
|
|
return v
|
|
}
|
|
return "/v1/base"
|
|
}
|
|
|
|
func redirect(re *core.RequestEvent) error {
|
|
rest := strings.TrimPrefix(re.Request.URL.Path, "/v1/files")
|
|
if rest == "" {
|
|
rest = "/"
|
|
}
|
|
target := basePrefix() + "/files" + rest
|
|
if re.Request.URL.RawQuery != "" {
|
|
target += "?" + re.Request.URL.RawQuery
|
|
}
|
|
// 307 preserves method + body. 308 would also work but Safari < 14
|
|
// is buggy with cached 308s; 307 is the safe default.
|
|
http.Redirect(re.Response, re.Request, target, http.StatusTemporaryRedirect)
|
|
return nil
|
|
}
|