httpserver

package
v0.4.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2025 License: BSD-3-Clause Imports: 18 Imported by: 0

README

httpserver

The httpserver package implements the core functionality of a coder-based http server.

Getting Started

package main

import (
	"encoding/json"
	"net/http"

	"github.com/easysy/proton/coder"
	"github.com/easysy/proton/httpserver"
)

func main() {
	cdrJSON := coder.NewCoder("application/json", json.Marshal, json.Unmarshal)

	fmtJSON := httpserver.NewFormatter(cdrJSON)

	handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()

		if r.Method != http.MethodGet {
			req := &struct {
				// some fields
			}{}

			if err := fmtJSON.Decode(ctx, r.Body, req); err != nil {
				panic(err)
			}
		}

		res := &struct {
			ID int `json:"id"`
		}{ID: 1}

		fmtJSON.WriteResponse(ctx, w, http.StatusOK, res)
	})

	http.Handle("/example/", handlerFunc)

	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}

For all responses with a body:
  • The default is to use the Content-Type set in the coder.
  • If you don't set the Content-Type in the coder, it will be set automatically by the net/http package.
  • If you need to set a different Content-Type you must set it before calling WriteResponse.
For all responses without a body:
  • Content-Type will not be set by default.
  • If you need to set Content-Type you must set it before calling WriteResponse.
package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/easysy/proton/httpserver"
)

func main() {
	handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		_, _ = fmt.Fprint(w, "Hello!")
	})

	handler := http.NewServeMux()
	handler.HandleFunc("/example/", handlerFunc)

	srv := new(http.Server)
	srv.Addr = ":8080"
	srv.Handler = handler

	hcr := new(httpserver.Controller)
	hcr.Server = srv
	hcr.GracefulTimeout = time.Second * 10

	if err := hcr.Start(); err != nil {
		panic(err)
	}
}

The httpserver package contains functions that are used as middleware on the http server side.

Getting Started

package main

import (
	"fmt"
	"log/slog"
	"net/http"

	"github.com/easysy/proton/httpserver"
)

func main() {
	handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if _, err := fmt.Fprintln(w, "Hello World!"); err != nil {
			panic(err)
		}
	})

	http.Handle("/example/", handlerFunc)

	corsOpts := new(httpserver.CORSOptions)

	corsOpts.AllowOrigins = []string{"*"}
	corsOpts.AllowMethods = []string{"OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE"}
	corsOpts.AllowHeaders = []string{"Authorization", "Content-Type"}
	corsOpts.MaxAge = 86400
	corsOpts.AllowCredentials = false

	handler := httpserver.MiddlewareSequencer(
		http.DefaultServeMux,
		httpserver.DumpHttp(slog.LevelDebug, 1024),
		httpserver.Timer(slog.LevelInfo),
		httpserver.Tracer,
		httpserver.AllowCORS(corsOpts),
		httpserver.PanicCatcher,
	)

	if err := http.ListenAndServe(":8080", handler); err != nil {
		panic(err)
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AllowCORS

func AllowCORS(opts *CORSOptions) func(next http.Handler) http.Handler

AllowCORS sets headers for CORS mechanism supports secure.

func DumpHttp

func DumpHttp(level slog.Level, maxBody int64) func(http.Handler) http.Handler

DumpHttp dumps the HTTP request and response, and prints out.

func MiddlewareSequencer

func MiddlewareSequencer(baseHandler http.Handler, mws ...func(http.Handler) http.Handler) http.Handler

MiddlewareSequencer chains middleware functions in a chain.

func PanicCatcher

func PanicCatcher(next http.Handler) http.Handler

PanicCatcher handles panics in http.HandlerFunc.

func Timer

func Timer(level slog.Level) func(http.Handler) http.Handler

Timer measures the time taken by http.HandlerFunc.

func Tracer

func Tracer(next http.Handler) http.Handler

Tracer adds trace ID to the request context.

Types

type CORSOptions

type CORSOptions struct {
	// AllowOriginsFunc is an optional callback to dynamically allow or reject an origin.
	// If provided, it takes precedence over AllowOrigins.
	AllowOriginsFunc func(string) bool

	// AllowOrigins is the list of allowed origins.
	// An empty slice or a list containing "*" means all origins are allowed.
	AllowOrigins []string

	// AllowMethods is the list of allowed HTTP methods.
	// An empty slice or a list containing "*" means all methods are allowed.
	AllowMethods []string

	// AllowHeaders is the list of allowed request headers.
	// An empty slice or a list containing "*" means all headers are allowed.
	AllowHeaders []string

	// ExposeHeaders are the response headers that browsers are allowed to access
	// via client-side JavaScript (using XMLHttpRequest or Fetch).
	ExposeHeaders []string

	// MaxAge is the number of seconds a preflight request can be cached by the client.
	MaxAge int

	// AllowCredentials indicates whether cookies, authorization headers, and TLS
	// client certificates are exposed to the browser.
	AllowCredentials bool

	// AllowPrivateNetwork indicates whether requests from private network contexts
	// are allowed (controlled via the "Private-Network" CORS extension header).
	AllowPrivateNetwork bool

	// SkipStrictOriginCheck controls how requests without a valid Origin header are handled.
	//
	// By default, (false), requests missing an allowed Origin are rejected, ensuring strict
	// cross-origin enforcement for both preflight (OPTIONS) and non-preflight requests.
	//
	// If set to true, non-preflight requests (e.g., GET, POST) that do not include an
	// Origin header are allowed to pass through to the next handler. This is useful for:
	//
	//   - Same-origin requests (browsers often omit the Origin header)
	//   - Non-browser clients (curl, Go http.Client, etc.) that do not set Origin
	//
	// Security note: Setting this to true means requests without Origin are trusted.
	// You should only enable it if your API must support same-origin or non-browser clients.
	SkipStrictOriginCheck bool
}

CORSOptions represents configuration for the CORS middleware.

type Controller

type Controller struct {
	Server          *http.Server
	GracefulTimeout time.Duration
	// contains filtered or unexported fields
}

Controller is a wrapper around *http.Server to control the server.

Server — *http.Server, which will be managed.
GracefulTimeout — time that is given to the server to shut down gracefully.

func (*Controller) OnStart added in v0.2.0

func (c *Controller) OnStart(f func(*http.Server))

OnStart registers a callback function that is executed every time the controller starts or restarts. The provided function `f` receives a pointer to the HTTP server managed by the controller, allowing the user to perform custom initialization or configuration tasks at startup.

func (*Controller) Restart

func (c *Controller) Restart()

Restart restarts the server if necessary. For changes to the following parameters to take effect:

Addr; TLSConfig; TLSNextProto; ConnState; BaseContext; ConnContext,

a server restart is required. Other parameters can be changed without restarting the server. If the server is not running, the function will be skipped.

func (*Controller) Shutdown

func (c *Controller) Shutdown()

Shutdown gracefully shuts down the server.

func (*Controller) Start

func (c *Controller) Start() (err error)

Start starts the *http.Server. If *tls.Config on the server is non nil, the server listens and serves using tls.

type Formatter

type Formatter interface {
	coder.Coder
	WriteResponse(ctx context.Context, w http.ResponseWriter, statusCode int, v any)
}

func NewFormatter

func NewFormatter(coder coder.Coder) Formatter

NewFormatter returns a new Formatter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL