http API

http

package

API reference for the http package.

T
type

Handler

pkg/http/engine.go:5-5
type Handler any
T
type

Middleware

pkg/http/engine.go:6-6
type Middleware func(Handler) Handler
I
interface

Engine

pkg/http/engine.go:8-17
type Engine interface

Methods

Handle
Method

Parameters

method string
path string
func Handle(...)
Use
Method

Parameters

func Use(...)
Group
Method

Parameters

prefix string

Returns

func Group(...)
Serve
Method

Parameters

addr string

Returns

error
func Serve(...)
Shutdown
Method

Parameters

Returns

error
func Shutdown(...)
Unwrap
Method

Returns

any
func Unwrap(...)
S
struct

fastGroup

pkg/http/fasthttp.go:10-10
type fastGroup struct

Methods

Handle
Method

Parameters

m string
p string
func (*fastGroup) Handle(m, p string, h Handler)
{
	fg.g.Handle(m, p, h.(fasthttp.RequestHandler))
}
Use
Method

Parameters

func (*fastGroup) Use(Middleware)
{}
Group
Method

Parameters

prefix string

Returns

func (*fastGroup) Group(prefix string) Engine
{ return &fastGroup{g: fg.g.Group(prefix)} }
Serve
Method

Parameters

string

Returns

error
func (*fastGroup) Serve(string) error
{ return nil }
Shutdown
Method

Parameters

Returns

error
func (*fastGroup) Shutdown(context.Context) error
{ return nil }
Unwrap
Method

Returns

any
func (*fastGroup) Unwrap() any
{ return fg.g }

Fields

Name Type Description
g *router.Group
S
struct

FastHTTP

pkg/http/fasthttp.go:21-25
type FastHTTP struct

Methods

Handle
Method

Parameters

m string
p string
func (*FastHTTP) Handle(m, p string, h Handler)
{
	final := h.(fasthttp.RequestHandler)
	for i := len(f.mwChain) - 1; i >= 0; i-- {
		final = f.mwChain[i](final).(fasthttp.RequestHandler)
	}
	f.r.Handle(m, p, final)
}
Use
Method

Parameters

func (*FastHTTP) Use(mw Middleware)
{ f.mwChain = append(f.mwChain, mw) }
Group
Method

Parameters

prefix string

Returns

func (*FastHTTP) Group(prefix string) Engine
{
	return &fastGroup{g: f.r.Group(prefix)}
}
Serve
Method

Parameters

addr string

Returns

error
func (*FastHTTP) Serve(addr string) error
{
	f.srv = &fasthttp.Server{Handler: f.r.Handler}
	return f.srv.ListenAndServe(addr)
}
Shutdown
Method

Parameters

Returns

error
func (*FastHTTP) Shutdown(ctx context.Context) error
{
	if f.srv == nil {
		return nil
	}
	return f.srv.ShutdownWithContext(ctx)
}
Unwrap
Method

Returns

any
func (*FastHTTP) Unwrap() any
{ return f.r }

Fields

Name Type Description
r *router.Router
mwChain []Middleware
srv *fasthttp.Server
F
function

NewFastHTTP

Returns

pkg/http/fasthttp.go:27-29
func NewFastHTTP() *FastHTTP

{
	return &FastHTTP{r: router.New()}
}
S
struct

StdHTTP

pkg/http/stdhttp.go:8-12
type StdHTTP struct

Methods

Handle
Method

Parameters

m string
p string
func (*StdHTTP) Handle(m, p string, h Handler)
{
	final := h.(http.Handler)
	for i := len(s.mwChain) - 1; i >= 0; i-- {
		final = s.mwChain[i](final).(http.Handler)
	}

	switch m {
	case http.MethodGet:
		s.mux.Handle(p, final)
	default:
		s.mux.HandleFunc(p, func(w http.ResponseWriter, r *http.Request) {
			if r.Method != m {
				http.NotFound(w, r)
				return
			}
			final.ServeHTTP(w, r)
		})
	}
}
Use
Method

Parameters

func (*StdHTTP) Use(mw Middleware)
{ s.mwChain = append(s.mwChain, mw) }
Group
Method

Parameters

prefix string

Returns

func (*StdHTTP) Group(prefix string) Engine
{
	sub := NewStdHTTP()
	sub.mwChain = s.mwChain
	s.mux.Handle(prefix+"/", http.StripPrefix(prefix, sub.mux))
	return sub
}
Serve
Method

Parameters

addr string

Returns

error
func (*StdHTTP) Serve(addr string) error
{
	s.srv = &http.Server{Addr: addr, Handler: s.mux}
	return s.srv.ListenAndServe()
}
Shutdown
Method

Parameters

Returns

error
func (*StdHTTP) Shutdown(ctx context.Context) error
{
	if s.srv == nil {
		return nil
	}
	return s.srv.Shutdown(ctx)
}
Unwrap
Method

Returns

any
func (*StdHTTP) Unwrap() any
{ return s.mux }

Fields

Name Type Description
mux *http.ServeMux
mwChain []Middleware
srv *http.Server
F
function

NewStdHTTP

Returns

pkg/http/stdhttp.go:14-16
func NewStdHTTP() *StdHTTP

{
	return &StdHTTP{mux: http.NewServeMux()}
}
S
struct

Transport

Transport handles HTTP-based routing.

pkg/transport/http/transport.go:17-24
type Transport struct

Methods

Provide
Method

Provide registers a dependency.

Parameters

name string
instance any
func (*Transport) Provide(name string, instance any)
{
	t.container.Provide(name, instance)
}
Use
Method

Use adds middleware.

Parameters

mw func(http.Handler) http.Handler
func (*Transport) Use(mw func(http.Handler) http.Handler)
{
	t.middleware = append(t.middleware, mw)
}
Group
Method

Group creates a sub-transport with a prefix.

Parameters

prefix string

Returns

func (*Transport) Group(prefix string) *Transport
{
	return &Transport{
		mux:        t.mux,
		container:  t.container,
		Logger:     t.Logger,
		middleware: append([]func(http.Handler) http.Handler(nil), t.middleware...),
		prefix:     t.prefix + prefix,
	}
}
Register
Method

Register adds an HTTP endpoint. Reads `method:"GET"` and `path:"/users/{id}"` tags from Pattern field.

Parameters

prototype core.Handler
func (*Transport) Register(prototype core.Handler)
{
	t.handlers = append(t.handlers, prototype)
	val := reflect.ValueOf(prototype)
	if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Struct {
		panic("Transport.Register: prototype must be a pointer to a struct")
	}

	elemType := val.Elem().Type()

	var method, path string
	for i := 0; i < elemType.NumField(); i++ {
		field := elemType.Field(i)
		if field.Type == reflect.TypeOf(core.Pattern{}) {
			method = field.Tag.Get("method")
			path = field.Tag.Get("path")
			break
		}
	}

	if method == "" || path == "" {
		panic(fmt.Sprintf("Transport.Register: struct %s missing Pattern with method/path tags", elemType.Name()))
	}

	fullPath := t.prefix + path
	pattern := fmt.Sprintf("%s %s", method, fullPath)

	t.Logger.Info("Registering route", "route", pattern, "handler", elemType.Name())

	var finalHandler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		// Create new instance
		newVal := reflect.New(elemType).Elem()
		newVal.Set(val.Elem())

		instance := newVal.Addr().Interface()

		// Inject dependencies
		t.container.Inject(instance)

		// Bind request data
		binder := core.NewBinder()
		binder.AddSource("path", func(key string) string { return req.PathValue(key) })
		binder.AddSource("query", func(key string) string { return req.URL.Query().Get(key) })
		binder.AddSource("header", func(key string) string { return req.Header.Get(key) })

		if err := binder.Bind(instance); err != nil {
			http.Error(w, fmt.Sprintf("Bad Request: %v", err), http.StatusBadRequest)
			return
		}

		// Bind JSON body if present
		contentType := req.Header.Get("Content-Type")
		if req.Body != nil && strings.HasPrefix(contentType, "application/json") {
			body, _ := io.ReadAll(req.Body)
			if len(body) > 0 {
				binder.BindJSON(instance, body)
			}
		}

		// Execute
		handler := instance.(core.Handler)

		// Inject HTTP context
		ctx := req.Context()
		ctx = context.WithValue(ctx, "http_request", req)
		ctx = context.WithValue(ctx, "http_response_writer", w)

		resp, err := handler.Handle(ctx)
		if err != nil {
			t.Logger.Error("Handler failed", "error", err)

			code := http.StatusInternalServerError
			var resp any = map[string]string{"error": err.Error()}

			// Check for optional interfaces
			type StatusCoder interface {
				StatusCode() int
			}
			type Payloader interface {
				Payload() any
			}

			if sc, ok := err.(StatusCoder); ok {
				code = sc.StatusCode()
			}
			if pl, ok := err.(Payloader); ok {
				resp = pl.Payload()
			}

			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(code)
			json.NewEncoder(w).Encode(resp)
			return
		}

		// Write response
		if resp != nil {
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(resp)
		} else {
			w.WriteHeader(http.StatusNoContent)
		}
	})

	// Apply middleware
	for i := len(t.middleware) - 1; i >= 0; i-- {
		finalHandler = t.middleware[i](finalHandler)
	}

	t.mux.Handle(pattern, finalHandler)
}
Listen
Method

Listen starts the HTTP server.

Parameters

addr string

Returns

error
func (*Transport) Listen(addr string) error
{
	t.Logger.Info("HTTP transport listening", "addr", addr)
	return http.ListenAndServe(addr, t.mux)
}
Shutdown
Method

Shutdown gracefully shuts down.

Parameters

Returns

error
func (*Transport) Shutdown(ctx context.Context) error
{
	return nil
}
ServeHTTP
Method

ServeHTTP implements http.Handler.

Parameters

func (*Transport) ServeHTTP(w http.ResponseWriter, req *http.Request)
{
	t.mux.ServeHTTP(w, req)
}
Mux
Method

Mux returns the underlying ServeMux.

Returns

func (*Transport) Mux() *http.ServeMux
{
	return t.mux
}
Handlers
Method

Handlers returns all registered handlers (for Swagger generation).

Returns

func (*Transport) Handlers() []core.Handler
{
	return t.handlers
}

Fields

Name Type Description
mux *http.ServeMux
container *core.Container
Logger logger.Logger
middleware []func(http.Handler) http.Handler
prefix string
handlers []core.Handler
F
function

New

New creates a new HTTP transport.

Returns

pkg/transport/http/transport.go:27-33
func New() *Transport

{
	return &Transport{
		mux:       http.NewServeMux(),
		container: core.NewContainer(),
		Logger:    logger.Nop,
	}
}