mirror of
https://github.com/zap-proto/http.git
synced 2026-10-04 03:07:19 +00:00
The package is called http and now looks like it. Request, Response, Header,
Handler, HandlerFunc, ResponseWriter and ServeMux are ALIASES of net/http's own
types, so an existing handler satisfies them exactly and middleware, httptest
and mux compose for free. A declared struct with matching fields would be a
different type — every caller converting, every middleware failing — and drop-in
would be a claim rather than a fact.
ListenAndServe takes the standard Handler, and there is one of it. A second one
taking fasthttp.RequestHandler used to sit in server.go, so there were two ways
to start a server differing only in which handler shape you happened to hold. A
caller with a fasthttp handler composes &Server{Addr, Handler} — one line that
says what it is.
The cost is named rather than hidden: net/http's Request and ResponseWriter
allocate where fasthttp's do not, and this package guards a zero-alloc encode.
So the fast path is untouched — Server.Handler is still a fasthttp handler and
nothing in this file is in its way. Adapt is exported so the bridge is visible at
the call site, which is where a net/http Request gets materialised.
The example is an ordinary net/http handler now. Nothing in it knows about ZAP,
which is the whole demonstration.
Co-authored-by: Hanzo Dev <[email protected]>
53 lines
1.5 KiB
Go
53 lines
1.5 KiB
Go
// Minimal zap-http example: server + client in one binary.
|
|
//
|
|
// go run ./examples/hello server :9999
|
|
// go run ./examples/hello client :9999
|
|
//
|
|
// The server speaks ZAP-HTTP on :9999 with a fasthttp handler. The client
|
|
// dials, issues GET /hello, and prints the response body.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
http "github.com/zap-proto/http"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 3 {
|
|
fmt.Fprintf(os.Stderr, "usage: %s [server|client] addr\n", os.Args[0])
|
|
os.Exit(2)
|
|
}
|
|
role, addr := os.Args[1], os.Args[2]
|
|
|
|
switch role {
|
|
case "server":
|
|
// An ordinary net/http handler. Nothing here knows about ZAP — that is
|
|
// the point: the import changed and the code did not.
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
fmt.Fprintf(w, "hello from %s — you said %s %s\n", addr, r.Method, r.URL.Path)
|
|
})
|
|
fmt.Printf("zap-http server listening on %s\n", addr)
|
|
if err := http.ListenAndServe(addr, handler); err != nil {
|
|
fmt.Fprintln(os.Stderr, "server:", err)
|
|
os.Exit(1)
|
|
}
|
|
case "client":
|
|
resp, err := http.Get(addr, "/hello")
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "client:", err)
|
|
os.Exit(1)
|
|
}
|
|
defer fasthttp.ReleaseResponse(resp)
|
|
fmt.Printf("← %d %s\n", resp.StatusCode(), fasthttp.StatusMessage(resp.StatusCode()))
|
|
os.Stdout.Write(resp.Body())
|
|
default:
|
|
fmt.Fprintln(os.Stderr, "role must be 'server' or 'client'")
|
|
os.Exit(2)
|
|
}
|
|
}
|