pingpong

package module
v0.0.0-...-f98629b Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2024 License: MIT Imports: 22 Imported by: 0

README

ping-pong

Lightweight HTTP webserver for use and learning

Documentation

Index

Constants

View Source
const (

	// PROPFIND Method can be used on collection and property resources.
	PROPFIND = "PROPFIND"
	// REPORT Method can be used to get information about a resource, see rfc 3253
	REPORT = "REPORT"
	// RouteNotFound is special method type for routes handling "route not found" (404) cases
	RouteNotFound = "echo_route_not_found"
)
View Source
const (
	// MIMEApplicationJSON JavaScript Object Notation (JSON) https://www.rfc-editor.org/rfc/rfc8259
	MIMEApplicationJSON = "application/json"

	MIMEApplicationJavaScript            = "application/javascript"
	MIMEApplicationJavaScriptCharsetUTF8 = MIMEApplicationJavaScript + "; " + charsetUTF8
	MIMEApplicationXML                   = "application/xml"
	MIMEApplicationXMLCharsetUTF8        = MIMEApplicationXML + "; " + charsetUTF8
	MIMETextXML                          = "text/xml"
	MIMETextXMLCharsetUTF8               = MIMETextXML + "; " + charsetUTF8
	MIMEApplicationForm                  = "application/x-www-form-urlencoded"
	MIMEApplicationProtobuf              = "application/protobuf"
	MIMEApplicationMsgpack               = "application/msgpack"
	MIMETextHTML                         = "text/html"
	MIMETextHTMLCharsetUTF8              = MIMETextHTML + "; " + charsetUTF8
	MIMETextPlain                        = "text/plain"
	MIMETextPlainCharsetUTF8             = MIMETextPlain + "; " + charsetUTF8
	MIMEMultipartForm                    = "multipart/form-data"
	MIMEOctetStream                      = "application/octet-stream"
)

MIME types

View Source
const (
	HeaderAccept         = "Accept"
	HeaderAcceptEncoding = "Accept-Encoding"
	// HeaderAllow is the name of the "Allow" header field used to list the set of methods
	// advertised as supported by the target resource. Returning an Allow header is mandatory
	// for status 405 (method not found) and useful for the OPTIONS method in responses.
	// See RFC 7231: https://datatracker.ietf.org/doc/html/rfc7231#section-7.4.1
	HeaderAllow               = "Allow"
	HeaderAuthorization       = "Authorization"
	HeaderContentDisposition  = "Content-Disposition"
	HeaderContentEncoding     = "Content-Encoding"
	HeaderContentLength       = "Content-Length"
	HeaderContentType         = "Content-Type"
	HeaderCookie              = "Cookie"
	HeaderSetCookie           = "Set-Cookie"
	HeaderIfModifiedSince     = "If-Modified-Since"
	HeaderLastModified        = "Last-Modified"
	HeaderLocation            = "Location"
	HeaderRetryAfter          = "Retry-After"
	HeaderUpgrade             = "Upgrade"
	HeaderVary                = "Vary"
	HeaderWWWAuthenticate     = "WWW-Authenticate"
	HeaderXForwardedFor       = "X-Forwarded-For"
	HeaderXForwardedProto     = "X-Forwarded-Proto"
	HeaderXForwardedProtocol  = "X-Forwarded-Protocol"
	HeaderXForwardedSsl       = "X-Forwarded-Ssl"
	HeaderXUrlScheme          = "X-Url-Scheme"
	HeaderXHTTPMethodOverride = "X-HTTP-Method-Override"
	HeaderXRealIP             = "X-Real-Ip"
	HeaderXRequestID          = "X-Request-Id"
	HeaderXCorrelationID      = "X-Correlation-Id"
	HeaderXRequestedWith      = "X-Requested-With"
	HeaderServer              = "Server"
	HeaderOrigin              = "Origin"
	HeaderCacheControl        = "Cache-Control"
	HeaderConnection          = "Connection"

	// Access control
	HeaderAccessControlRequestMethod    = "Access-Control-Request-Method"
	HeaderAccessControlRequestHeaders   = "Access-Control-Request-Headers"
	HeaderAccessControlAllowOrigin      = "Access-Control-Allow-Origin"
	HeaderAccessControlAllowMethods     = "Access-Control-Allow-Methods"
	HeaderAccessControlAllowHeaders     = "Access-Control-Allow-Headers"
	HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
	HeaderAccessControlExposeHeaders    = "Access-Control-Expose-Headers"
	HeaderAccessControlMaxAge           = "Access-Control-Max-Age"

	// Security
	HeaderStrictTransportSecurity         = "Strict-Transport-Security"
	HeaderXContentTypeOptions             = "X-Content-Type-Options"
	HeaderXXSSProtection                  = "X-XSS-Protection"
	HeaderXFrameOptions                   = "X-Frame-Options"
	HeaderContentSecurityPolicy           = "Content-Security-Policy"
	HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
	HeaderXCSRFToken                      = "X-CSRF-Token"
	HeaderReferrerPolicy                  = "Referrer-Policy"
)

Headers

View Source
const (
	// ContextKeyHeaderAllow is set by Router for getting value for `Allow` header in later stages of handler call chain.
	// Allow header is mandatory for status 405 (method not found) and useful for OPTIONS method requests.
	// It is added to context only when Router does not find matching method handler for request.
	ContextKeyHeaderAllow = "pingpong_header_allow"
)
View Source
const (
	// Version of Echo
	Version = "0.0.1"
)

head of string when you run this server firstly

Variables

View Source
var (
	ErrBadRequest                    = NewHTTPError(http.StatusBadRequest)                    // HTTP 400 Bad Request
	ErrUnauthorized                  = NewHTTPError(http.StatusUnauthorized)                  // HTTP 401 Unauthorized
	ErrPaymentRequired               = NewHTTPError(http.StatusPaymentRequired)               // HTTP 402 Payment Required
	ErrForbidden                     = NewHTTPError(http.StatusForbidden)                     // HTTP 403 Forbidden
	ErrNotFound                      = NewHTTPError(http.StatusNotFound)                      // HTTP 404 Not Found
	ErrMethodNotAllowed              = NewHTTPError(http.StatusMethodNotAllowed)              // HTTP 405 Method Not Allowed
	ErrNotAcceptable                 = NewHTTPError(http.StatusNotAcceptable)                 // HTTP 406 Not Acceptable
	ErrProxyAuthRequired             = NewHTTPError(http.StatusProxyAuthRequired)             // HTTP 407 Proxy AuthRequired
	ErrRequestTimeout                = NewHTTPError(http.StatusRequestTimeout)                // HTTP 408 Request Timeout
	ErrConflict                      = NewHTTPError(http.StatusConflict)                      // HTTP 409 Conflict
	ErrGone                          = NewHTTPError(http.StatusGone)                          // HTTP 410 Gone
	ErrLengthRequired                = NewHTTPError(http.StatusLengthRequired)                // HTTP 411 Length Required
	ErrPreconditionFailed            = NewHTTPError(http.StatusPreconditionFailed)            // HTTP 412 Precondition Failed
	ErrStatusRequestEntityTooLarge   = NewHTTPError(http.StatusRequestEntityTooLarge)         // HTTP 413 Payload Too Large
	ErrRequestURITooLong             = NewHTTPError(http.StatusRequestURITooLong)             // HTTP 414 URI Too Long
	ErrUnsupportedMediaType          = NewHTTPError(http.StatusUnsupportedMediaType)          // HTTP 415 Unsupported Media Type
	ErrRequestedRangeNotSatisfiable  = NewHTTPError(http.StatusRequestedRangeNotSatisfiable)  // HTTP 416 Range Not Satisfiable
	ErrExpectationFailed             = NewHTTPError(http.StatusExpectationFailed)             // HTTP 417 Expectation Failed
	ErrTeapot                        = NewHTTPError(http.StatusTeapot)                        // HTTP 418 I'm a teapot
	ErrMisdirectedRequest            = NewHTTPError(http.StatusMisdirectedRequest)            // HTTP 421 Misdirected Request
	ErrUnprocessableEntity           = NewHTTPError(http.StatusUnprocessableEntity)           // HTTP 422 Unprocessable Entity
	ErrLocked                        = NewHTTPError(http.StatusLocked)                        // HTTP 423 Locked
	ErrFailedDependency              = NewHTTPError(http.StatusFailedDependency)              // HTTP 424 Failed Dependency
	ErrTooEarly                      = NewHTTPError(http.StatusTooEarly)                      // HTTP 425 Too Early
	ErrUpgradeRequired               = NewHTTPError(http.StatusUpgradeRequired)               // HTTP 426 Upgrade Required
	ErrPreconditionRequired          = NewHTTPError(http.StatusPreconditionRequired)          // HTTP 428 Precondition Required
	ErrTooManyRequests               = NewHTTPError(http.StatusTooManyRequests)               // HTTP 429 Too Many Requests
	ErrRequestHeaderFieldsTooLarge   = NewHTTPError(http.StatusRequestHeaderFieldsTooLarge)   // HTTP 431 Request Header Fields Too Large
	ErrUnavailableForLegalReasons    = NewHTTPError(http.StatusUnavailableForLegalReasons)    // HTTP 451 Unavailable For Legal Reasons
	ErrInternalServerError           = NewHTTPError(http.StatusInternalServerError)           // HTTP 500 Internal Server Error
	ErrNotImplemented                = NewHTTPError(http.StatusNotImplemented)                // HTTP 501 Not Implemented
	ErrBadGateway                    = NewHTTPError(http.StatusBadGateway)                    // HTTP 502 Bad Gateway
	ErrServiceUnavailable            = NewHTTPError(http.StatusServiceUnavailable)            // HTTP 503 Service Unavailable
	ErrGatewayTimeout                = NewHTTPError(http.StatusGatewayTimeout)                // HTTP 504 Gateway Timeout
	ErrHTTPVersionNotSupported       = NewHTTPError(http.StatusHTTPVersionNotSupported)       // HTTP 505 HTTP Version Not Supported
	ErrVariantAlsoNegotiates         = NewHTTPError(http.StatusVariantAlsoNegotiates)         // HTTP 506 Variant Also Negotiates
	ErrInsufficientStorage           = NewHTTPError(http.StatusInsufficientStorage)           // HTTP 507 Insufficient Storage
	ErrLoopDetected                  = NewHTTPError(http.StatusLoopDetected)                  // HTTP 508 Loop Detected
	ErrNotExtended                   = NewHTTPError(http.StatusNotExtended)                   // HTTP 510 Not Extended
	ErrNetworkAuthenticationRequired = NewHTTPError(http.StatusNetworkAuthenticationRequired) // HTTP 511 Network Authentication Required

	ErrValidatorNotRegistered = errors.New("validator not registered")
	ErrRendererNotRegistered  = errors.New("renderer not registered")
	ErrInvalidRedirectCode    = errors.New("invalid redirect status code")
	ErrCookieNotFound         = errors.New("cookie not found")
	ErrInvalidCertOrKeyType   = errors.New("invalid cert or key type, must be string or []byte")
	ErrInvalidListenerNetwork = errors.New("invalid listener network")
)

Errors

View Source
var MethodNotAllowedHandler = func(c Context) error {

	routerAllowMethods, ok := c.Get(ContextKeyHeaderAllow).(string)
	if ok && routerAllowMethods != "" {
		c.Response().Header().Set(HeaderAllow, routerAllowMethods)
	}
	return ErrMethodNotAllowed
}

MethodNotAllowedHandler is the handler thar router uses in case there was no matching route found but there was another matching routes for that requested URL. Returns an error that results HTTP 405 Method Not Allowed status code.

View Source
var NotFoundHandler = func(c Context) error {
	return ErrNotFound
}

NotFoundHandler is the handler that router uses in case there was no matching route found. Returns an error that results HTTP 404 status code.

Functions

func GetPath

func GetPath(r *http.Request) string

GetPath returns RawPath, if it's empty returns Path from URL Difference between RawPath and Path is:

  • Path is where request path is stored. Value is stored in decoded form: /%47%6f%2f becomes /Go/.
  • RawPath is an optional field which only gets set if the default encoding is different from Path.

Types

type Binder

type Binder interface {
	Bind(i interface{}, c Context) error
}

Binder is the interface that wraps the Bind method.

type Context

type Context interface {
	// Response returns `*Response`.
	Response() *Response

	// Request returns `*http.Request`.
	Request() *http.Request

	// Handler returns the matched handler by router.
	Handler() HandlerFunc

	// NoContent sends a response with no body and a status code.
	NoContent(code int) error

	// JSON sends a JSON response with status code.
	JSON(code int, i interface{}) error

	// String sends a string response with status code.
	String(code int, s string) error

	// QueryParams returns the query parameters as `url.Values`.
	QueryParams() url.Values

	// Set saves data in the context.
	Set(key string, val interface{})

	// Get retrieves data from the context.
	Get(key string) interface{}
}

type DefaultBinder

type DefaultBinder struct{}

DefaultBinder is the default implementation of the Binder interface.

func (*DefaultBinder) Bind

func (b *DefaultBinder) Bind(i interface{}, c Context) (err error)

Bind implements the `Binder#Bind` function. Binding is done in following order: 1) path params; 2) query params; 3) request body. Each step COULD override previous step binded values. For single source binding use their own methods BindBody, BindQueryParams, BindPathParams.

type DefaultJSONSerializer

type DefaultJSONSerializer struct{}

DefaultJSONSerializer implements JSON encoding using encoding/json.

func (DefaultJSONSerializer) Deserialize

func (d DefaultJSONSerializer) Deserialize(c Context, i interface{}) error

Deserialize reads a JSON from a request body and converts it into an interface.

func (DefaultJSONSerializer) Serialize

func (d DefaultJSONSerializer) Serialize(c Context, i interface{}, indent string) error

Serialize converts an interface into a json and writes it to the response. You can optionally use the indent parameter to produce pretty JSONs.

type HTTPError

type HTTPError struct {
	Internal error       `json:"-"` // Stores the error returned by an external dependency
	Message  interface{} `json:"message"`
	Code     int         `json:"-"`
}

HTTPError represents an error that occurred while handling a request.

func NewHTTPError

func NewHTTPError(code int, message ...interface{}) *HTTPError

func (*HTTPError) Error

func (h *HTTPError) Error() string

Error implements error.

func (*HTTPError) SetInternal

func (he *HTTPError) SetInternal(err error) *HTTPError

SetInternal sets error to HTTPError.Internal

type HTTPErrorHandler

type HTTPErrorHandler func(err error, c Context)

HTTPErrorHandler is a centralized HTTP error handler.

type HandlerFunc

type HandlerFunc func(c Context) error

HandlerFunc defines a function to serve HTTP requests.

type IPExtractor

type IPExtractor func(*http.Request) string

type JSONSerializer

type JSONSerializer interface {
	Serialize(c Context, i interface{}, indent string) error
	Deserialize(c Context, i interface{}) error
}

JSONSerializer is the interface that encodes and decodes JSON to and from interfaces.

type Map

type Map map[string]interface{}

Map defines a generic map of type `map[string]interface{}`.

type MiddlewareFunc

type MiddlewareFunc func(next HandlerFunc) HandlerFunc

MiddlewareFunc defines a function to process middleware.

type Pingpong

type Pingpong struct {
	StdLogger        *stdLog.Logger
	Logger           *slog.Logger
	Server           *http.Server
	TLSServer        *http.Server
	Listener         net.Listener
	TLSListener      net.Listener
	AutoTLSManager   autocert.Manager
	HTTPErrorHandler HTTPErrorHandler
	Binder           Binder
	JSONSerializer   JSONSerializer
	Validator        Validator
	Renderer         Renderer
	IPExtractor      IPExtractor
	ListenerNetwork  string

	// OnAddRouteHandler is called when PingPong adds new route to specific host router.
	OnAddRouteHandler func(host string, route Route, handler HandlerFunc, middleware []MiddlewareFunc)
	DisableHTTP2      bool
	Debug             bool
	HideBanner        bool
	HidePort          bool
	// contains filtered or unexported fields
}

Pingpong is the top-level framework instance Evrything happens in this web server or from this instance

func New

func New() (p *Pingpong)

create a new instance for PingPong

func (*Pingpong) Add

func (p *Pingpong) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route

Add registers a new route for an HTTP method and path with matching handler in the router with optional route-level middleware.

func (*Pingpong) DELETE

func (p *Pingpong) DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) *Route

DELETE registers a new DELETE route for a path with matching handler in the router with optional route-level middleware.

func (*Pingpong) DefaultHTTPErrorHandler

func (p *Pingpong) DefaultHTTPErrorHandler(err error, c Context)

DefaultHTTPErrorHandler is the default HTTP error handler. It sends a JSON response with status code.

NOTE: In case errors happens in middleware call-chain that is returning from handler (which did not return an error). When handler has already sent response (ala c.JSON()) and there is error in middleware that is returning from handler. Then the error that global error handler received will be ignored because we have already "committed" the response and status code header has been sent to the client.

func (*Pingpong) GET

func (p *Pingpong) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route

GET registers a new GET route for a path with matching handler in the router with optional route-level middleware.

func (*Pingpong) NewContext

func (p *Pingpong) NewContext(r *http.Request, w http.ResponseWriter) Context

NewContext returns a Context instance.

func (*Pingpong) POST

func (p *Pingpong) POST(path string, h HandlerFunc, m ...MiddlewareFunc) *Route

POST registers a new POST route for a path with matching handler in the router with optional route-level middleware.

func (*Pingpong) PUT

func (p *Pingpong) PUT(path string, h HandlerFunc, m ...MiddlewareFunc) *Route

PUT registers a new PUT route for a path with matching handler in the router with optional route-level middleware.

func (*Pingpong) Pre

func (p *Pingpong) Pre(middleware ...MiddlewareFunc)

Pre adds middleware to the chain which is run before router.

func (*Pingpong) ServeHTTP

func (p *Pingpong) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements `http.Handler` interface, which serves HTTP requests.

func (*Pingpong) Start

func (p *Pingpong) Start(address string) error

Start starts an HTTP server.

func (*Pingpong) Use

func (p *Pingpong) Use(middleware ...MiddlewareFunc)

Use adds middleware to the chain which is run after router.

type Renderer

type Renderer interface {
	Render(io.Writer, string, interface{}, Context) error
}

Renderer is the interface that wraps the Render function.

type Response

type Response struct {
	Writer http.ResponseWriter

	Status    int
	Size      int64
	Committed bool
	// contains filtered or unexported fields
}

Response wraps an http.ResponseWriter and implements its interface to be used by an HTTP handler to construct an HTTP response. See: https://golang.org/pkg/net/http/#ResponseWriter

func NewResponse

func NewResponse(w http.ResponseWriter, p *Pingpong) (r *Response)

NewResponse creates a new instance of Response.

func (*Response) Header

func (r *Response) Header() http.Header

Header returns the header map for the writer that will be sent by WriteHeader. Changing the header after a call to WriteHeader (or Write) has no effect unless the modified headers were declared as trailers by setting the "Trailer" header before the call to WriteHeader (see example) To suppress implicit response headers, set their value to nil. Example: https://golang.org/pkg/net/http/#example_ResponseWriter_trailers

func (*Response) Write

func (r *Response) Write(p []byte) (n int, err error)

Write implements io.Writer.

func (*Response) WriteHeader

func (r *Response) WriteHeader(code int)

WriteHeader sends an HTTP response header with status code. If WriteHeader is not called explicitly, the first call to Write will trigger an implicit WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly used to send error codes.

type Route

type Route struct {
	Method string `json:"method"`
	Path   string `json:"path"`
	Name   string `json:"name"`
}

Route contains a handler and information for matching against requests.

type Router

type Router struct {
	// contains filtered or unexported fields
}

A registry place for all routes in a pingpong instance

func NewRouter

func NewRouter(p *Pingpong) *Router

NewRouter returns a new Router instance.

func (*Router) Find

func (r *Router) Find(method, path string, c Context)

Find lookup a handler registered for method and path. It also parses URL for path parameters and load them into context.

For performance:

- Get context from `Echo#AcquireContext()` - Reset it `Context#Reset()` - Return it `Echo#ReleaseContext()`.

type Validator

type Validator interface {
	Validate(i interface{}) error
}

Validator is the interface that wraps the Validate function.

Jump to

Keyboard shortcuts

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