76 lines
2.2 KiB
Go
76 lines
2.2 KiB
Go
// This example only uses local HTTP and bounded streaming; it has no database.
|
|
package main
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
omni "git.yuntuo.hk/k2safe/go-omni"
|
|
"git.yuntuo.hk/k2safe/go-omni/contract"
|
|
"git.yuntuo.hk/k2safe/go-omni/examples/compatibility/ids"
|
|
"git.yuntuo.hk/k2safe/go-omni/httpx"
|
|
)
|
|
|
|
type echoRequest struct {
|
|
ID ids.ID `json:"id"`
|
|
Data any `json:"data"`
|
|
}
|
|
|
|
func main() {
|
|
app := omni.New(omni.WithLogger(true))
|
|
defer app.Close()
|
|
app.Use(httpx.WrapMiddleware(func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("X-Example", "compatibility")
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}))
|
|
app.GET("/legacy", httpx.WrapHandler(http.HandlerFunc(http.NotFound)))
|
|
binder := contract.MustNew[echoRequest](contract.ScalarOf[ids.ID]("string|int64", "string", true))
|
|
app.POST("/echo", func(c *httpx.Context) error {
|
|
var req echoRequest
|
|
if err := binder.Bind(c.Request(), nil, &req); err != nil {
|
|
return err
|
|
}
|
|
return c.OK(req)
|
|
})
|
|
app.HandleWithBodyLimit("POST", "/upload", 10<<20, nil, func(c *httpx.Context) error {
|
|
reader, err := c.Request().MultipartReader()
|
|
if err != nil {
|
|
return omni.BadRequest("INVALID_MULTIPART", "multipart body required")
|
|
}
|
|
var total int64
|
|
for {
|
|
part, err := reader.NextPart()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Replace io.Discard with a streaming storage writer. Do not trust file names
|
|
// as filesystem paths. io.Copy never buffers the complete uploaded file.
|
|
n, copyErr := io.Copy(io.Discard, part)
|
|
closeErr := part.Close()
|
|
if copyErr != nil {
|
|
return copyErr
|
|
}
|
|
if closeErr != nil {
|
|
return closeErr
|
|
}
|
|
total += n
|
|
}
|
|
return c.OK(map[string]int64{"bytes": total})
|
|
})
|
|
app.GET("/download", httpx.WrapHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
w.Header().Set("Content-Disposition", `attachment; filename="example.txt"`)
|
|
_, _ = io.Copy(w, strings.NewReader("A standard Handler keeps its original download response.\n"))
|
|
})))
|
|
if err := app.Run("127.0.0.1:8080"); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|