// 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) } }