hap

package module
v2.0.0-beta.19 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 22 Imported by: 0

README

HAP

This package implements a declarative HTTP framework for rapid API service development. Key features include:

  1. Code-as-Specification: API definitions serve as documentation specifications. The framework automatically generates API documentation directly from code-based endpoint declarations.

  2. Layered Processing Isolation: Separation of concerns between parameter validation and business logic, with framework-enforced validation pipeline definition and execution.

  3. Composable Processing Pipelines: Both parameter handling and business logic support multi-stage function composition, with explicit streamlined processing rules.

  4. Standard Library Foundation: Native integration with Go's net/http package allows direct use of core primitives like Request and ResponseWriter, ensuring zero learning curve for developers familiar with standard HTTP handling patterns.

Structure and Conventions

HAP is not a full-stack framework, nor does it provide functionalities like ORM. Instead, it is a minimalist and opinionated framework. It divides a complete HTTP request handling process into three distinct phases: parameter processing, business logic processing, and response generation.

Parameter Processing

The parameter processing phase is responsible for extracting parameters from HTTP requests (parameter collection), converting them into the format required by the business logic, and performing necessary validation (parameter validation).

Parameter Collection

The parameters of an HTTP request can be sourced from:

  • URL Path Parameters: For example, if a Handler's Pattern is /user/{id}, then id is a URL path parameter.
  • URL Query Parameters: Used in GET requests, e.g., id and name in /user?id=123&name=foo.
  • HTTP Request Body: Used in POST requests. The framework supports parsing MIME types including application/json, application/x-www-form-urlencoded, and multipart/form-data.
  • HTTP Request Cookies: The framework automatically extracts all cookies from the request and includes them as parameters. Cookies are processed with the same priority rules as other parameter sources. For secure cookie setting, see the SetCookie function.
  • HTTP Request Headers: The framework extracts headers starting with X- into the parameter set. For example, X-User-ID: 123 is parsed as user-id=123 (Note: Parameter names are converted to lowercase for compatibility) .

Parameter Collection Rules:

  • Priority Order: If duplicate parameter names exist across sources, priority is determined in the order listed above. Path parameters have the highest priority, followed by query parameters, then the request body.
  • HTTP Method Flexibility: Regardless of the HTTP method (e.g., GET, POST), parameters can be placed in any allowed locations. For example, POST requests may include parameters in both the URL query string and the request body, following the defined priority order . This design ensures unified parameter handling across all methods while maintaining backward compatibility with standard practices.
  • JSON Request Body Handling: For MIME type application/json, the framework parses the JSON data into key/value pairs. Keys must be string, and values can be either string or []string. To bypass JSON parsing (e.g., for non-compliant JSON), either:
    • Omit the Content-Type header or set to a non-JSON type
    • Use the WithRawJSONBody function to disable JSON body parsing
Parameter Validation

HAP defines a chainable parameter processing workflow where one or more validation functions can be specified during parameter definition. For example:

hap.Register(api.New("/api/user/{id}").WithHandlers(
    handler.GET().WithParams(
        param.New[int]("id").WithCheckers(
            param.ValueBetween(1, 1000).WithHelp("User ID must be between 1-1000"),
        ).WithHelp("User ID")
    ).WithActions(handleUserGet).WithHelp("Get user details")
))

In the WithCheckers function, multiple validators can be added. These validators execute sequentially. If any validator fails, the framework returns 400 Bad Request and terminates processing. Note: This error might be returned as HTTP status code 200, see the Response section for details.

Empty Value Handling Convention

HAP adopts the "empty equals not provided" design convention:

  • String parameters: Empty strings are treated as if the parameter was not provided
  • Multi-value parameters: Only when all values are empty is the parameter considered missing
  • Default values: Empty strings trigger default value usage, consistent with missing parameters

Example:

// These cases will all trigger IsRequired() errors:
GET /api/user           // name parameter not provided
GET /api/user?name=     // name is empty string
GET /api/user?name=&name=  // all name values are empty

// Only this case will not trigger an error:
GET /api/user?name=alice  // name has non-empty value

The framework provides common validators, including:

  • ValueBetween: Value must be within a specified range
  • ValueLessThan: Value must be less than a specified value
  • ValueGreaterThan: Value must be greater than a specified value
  • TextIsOneOf: Value must match one of the specified strings
  • TextHasPrefix: Value must start with a specified string
  • TextConsistsOf: Value must contain only specified characters
  • Many others (see API documentation).

Custom validators can be created using NewChecker. Validators can not only verify compliance but also transform parameters. For example:

  • Convert validated strings to uppercase
  • Map input values to predefined indexes
Business Logic Processing

The business logic processing phase forms the core of the framework, defined by the WithActions function which accepts one or more Action functions. These functions execute sequentially, and the next function's execution depends on the previous function's return value. The interface of an Action function is defined as:

func(*arg.Args, http.ResponseWriter, *http.Request) any

The first parameter is a pointer to the aggregated parameters from previous stage. It enables in-place modifications that propagate through the action chain.

The return value is of type any, but the permitted types and their meanings are limited to:

  • nil: Indicates the response has been completely handled within the Action (e.g., image/file data sent directly through ResponseWriter). The framework terminates processing immediately without additional returns.
  • ReplySpec: Represents the final processing result to be returned to the client.
  • error: Triggers a 500 Internal Server Error response with error details.
  • *arg.Args: Signals continuation of processing chain with modified parameters.

Note: If Action returns data other than the above types, the framework will panic. Both returned errors and panics will ultimately be wrapped into ReplySpec structures. The final response format (JSON or RAW) depends on the current "response mode" configuration (see Response section).

Response

The framework provides two return modes: API mode and RAW mode. It is important to note that the return modes discussed here only apply to cases where the Action function returns a ReplySpec (of course, if an error is returned or a panic is caught, it will also be converted into a ReplySpec). If the Action function returns nil, it means the response content is actually provided by the Action function itself, and the framework has no control over it.

API Mode

In this mode, regardless of the result of the Action function, the framework will always return an HTTP status code of 200 and convert the response to JSON format. For example, if a validator returns an error during the parameter processing phase, the framework will return a 400 error code embedded in the JSON body (not as the HTTP status code).

For instance, the following code:

return hap.Reply(http.StatusBadRequest).WithMesg("Missing required parameter 't'")  

will produce:

HTTP/1.1 200 OK  
Content-Type: application/json  
...  

{  
    "code": 400,  
    "mesg": "Missing required parameter 't'"  
}
RAW Mode

If th.e Action function returns a RawReply instead of a Reply, for example:

return hap.RawReply(http.StatusOK).WithData(data)  

the framework will not return JSON but directly output the raw data:

HTTP/1.1 200 OK  
Content-Type: application/octet-stream  
...  

[data]  
Special Cases
  • Errors or Panics: If the Action function returns an error or a panic is caught, the framework defaults to API mode for the response format. This behavior can be switched to RAW mode by using WithRawReply when defining the handler.
  • Forced RAW Mode: Regardless of the framework's global return mode setting, the following scenarios always enforce RAW mode:
    • Non-existent API endpoints: The framework directly returns a raw HTTP response with status code 404 Not Found.
    • Unhandled HTTP methods: The framework returns a raw HTTP response with status code 405 Method Not Allowed.

Implementation Examples

i18n Support

HAP handles i18n by using Go's standard internationalization library (golang.org/x/text). The framework processes Accept-Language headers following RFC 7231 specifications while providing high-level abstractions. The key implementation lies in the following code snippet from ServeHTTP:

lang := internal.MatchPreferredLanguage(r)  
a.i18nOut = message.NewPrinter(lang)  
w.Header().Set("Content-Language", lang.String())  

The internal MatchPreferredLanguage function is the core of this mechanism.

Under the internal package, the internal/lang_cn.go file demonstrates how to add Simplified Chinese translations for framework-level strings. Note that the language is only "registered" but not "activated". To actually use that language use the LoadLanguage function. This function also accepts a map containing extra translations. To add more languages, call LoadLanguage multiple times, once for each language. Note:

  • It is not mandatory to register a language before using LoadLanguage. As a matter of fact, the translations shown in internal/lang_cn.go can also be passed to LoadLanguage via the extra parameter.
  • You may also use go's [message.SetString] function to register individual translations directly.
Distributed Tracing Integration

HAP integrates with the W3C TraceContext compliant Traceparent identifier to facilitate distributed tracing systems.

When requests are routed to the framework via Go's http.ServeMux, ServeHTTP automatically generates a TraceContext object in the context. This object persists throughout the entire request lifecycle, recording all information from request initiation to response completion.

Before returning the response, the framework invokes function registered via WithPostResponseTrace. This function can export the TraceContext data to third-party logging systems. Complete implementation example:

func ValidateToken(a *arg.Args, w http.ResponseWriter, r *http.Request) any {
    t := arg.Get[string](a, "t")
    user, err := CheckToken(t)
    if err != nil {
        return hap.Reply(http.StatusUnauthorized).WithHelp(err.Error())
    }
    if tc := hap.GetTraceContext(r); tc != nil {
        tc.Index("user_login", user.Login)
    }
    return a
}

func handleUserGet(a *arg.Args, w http.ResponseWriter, r *http.Request) any {
    // Business logic implementation
}

func main() {
    // ...
    // Register API endpoint
    hap.Register(api.New("/api/users").WithHandlers(
        handler.GET().WithParams(
            param.New[string]("t").IsRequired().WithHelp("Access token"),
        ).WithActions(
            ValidateToken,
            handleUserGet
        ).WithHelp("Retrieve user information"),
    ))
    // Configure tracing export
    hap.WithPostResponseTrace(func(r *http.Request) {
        tc := hap.GetTraceContext(r)
        if tc == nil {
            return
        }
        tracer := otel.Tracer("hap.service")
        traceID, _ := otelTrace.TraceIDFromHex(tc.TraceId)
        spanID, _ := otelTrace.SpanIDFromHex(tc.SpanId)
        var parentSpanID otelTrace.SpanID
        if tc.ParentSpanId != "" {
            parentSpanID, _ = otelTrace.SpanIDFromHex(tc.ParentSpanId)
        }
        _, span := tracer.Start(
            context.Background(),
            tc.Route,
            otelTrace.WithSpanKind(otelTrace.SpanKindServer),
            otelTrace.WithTimestamp(time.Unix(0, tc.StartTime)),
            otelTrace.WithLinks(otelTrace.LinkFromContext(ctx)),
            otelTrace.WithTraceID(traceID),
            otelTrace.WithSpanID(spanID),
        )
        // Set standard attributes
        span.SetAttributes(
            attribute.String("service.name", tc.Service.Name),
            attribute.String("service.version", tc.Service.Version),
            attribute.String("service.instance.id", tc.Service.Address),
            attribute.String("deployment.environment", tc.Service.Environ),
            attribute.String("http.route", tc.Route),
            attribute.Int("http.status_code", tc.Reply.StatusCode()),
        )
        // ... ...
        for k, v := range tc.Indexes {
            span.SetAttributes(attribute.String(k, v))
        }
        for k, v := range tc.Props {
            span.SetAttributes(attribute.String(k, v))
        }
        span.End(otelTrace.WithTimestamp(time.Unix(0, tc.EndTime)))
    })
    // ...   
}
Self-Documenting System

One of HAP's core philosophies is self-documenting code. As demonstrated in previous sections, API endpoints automatically generate documentation through declarative helper functions (primarily WithHelp).

To enable API documentation generation, the framework provides the ListAPIs function:

var nr *hap.NetRange
if debugMode { // Default: localhost-only access. Debug mode opens to all IPs
    _, ns, _ := net.ParseCIDR("0.0.0.0/0")
    nr = hap.NewNetRange(*ns)
}
hap.Register(api.ListAPIs("/api", nr))

This registers an endpoint that lists all registered API information for documentation purposes. When registering the endpoint:

  • The NetRange object controls IP ranges that are allowed to get the list of APIs
  • In debug mode (0.0.0.0/0 CIDR) allows full access
  • In production mode (nil NetRange) only permits localhost access

The output of ListAPIs is a JSON object that can be read by documentation generation tools (please run the example program to view the specific output format).

Mock Data Service

When developing an API service, you can define the API specification and provide mock data to help frontend developers quickly build pages. HAP provides a mechanism to automatically return mock data through WithReplySpec. Below is an example:

hap.Register(api.New("/api/users/{id}").WithHandlers(
    handler.GET().WithParams(
        param.New[string]("t").IsRequired().WithHelp("Access token"),
        param.New[int]("id").IsRequired().WithHelp("User ID"),
    ).WithReplySpec(
        hap.Reply(http.StatusOK).WithData(map[string]any{
            "id": 1,
            "name": "John Doe",
        })),
        hap.Reply(http.StatusNotFound).WithHelp("User does not exist"),
    ).WithHelp("Get user information"),
)

Mechanism

  • If the API does not define specific business logic (i.e., it does not use WithActions), the framework will directly return the first mock data from ReplySpec.
  • If the API defines a business function but returns 501 Not Implemented, the framework will also return mock data.

Response Format

The returned mock data includes a prompt in the mesg field of the JSON response to indicate that the data is mock, helping frontend developers distinguish it from real data. For example:

{
    "code": 200,
    "data": {
        "id": 1,
        "name": "John Doe"
    },
    "mesg": "Mock data. Backend not implemented."
}

Documentation

Overview

Package hap provides secure cookie management utilities with sensible defaults.

The cookie functions follow security best practices by default:

  • HttpOnly: true (prevents XSS attacks)
  • Secure: auto-detected based on request TLS status
  • SameSite: Lax (prevents CSRF attacks while allowing normal navigation)
  • Path: "/" (cookie available site-wide)

Usage:

// Basic cookie with all secure defaults
hap.SetCookie(w, r, "session_id", "token123")

// Cookie with custom expiration
hap.SetCookie(w, r, "theme", "dark", hap.WithMaxAge(86400))

// Cookie for cross-subdomain sharing
hap.SetCookie(w, r, "user_prefs", "dark", hap.WithDomain(".example.com"))

// Delete a cookie (must match original domain/path)
hap.DelCookie(w, r, "session_id")
hap.DelCookie(w, r, "session_id", hap.WithDomain(".example.com"))

Index

Constants

View Source
const (
	TraceDisabled = TraceFlag(-1)
	TraceNoSample = TraceFlag(0)
	TraceSampled  = TraceFlag(1)
)

Variables

This section is empty.

Functions

func ApiOnExit

func ApiOnExit(r *http.Request, rep ReplySpec)

ApiOnExit is called internally by the framework to end the trace context, and call the registered tracer. If no tracer is registered, nothing happens.

func DebugMode

func DebugMode(onoff ...bool) bool

DebugMode exposes internal.DebugMode

func DelCookie

func DelCookie(w http.ResponseWriter, r *http.Request, key string, opts ...CookieOption)

DelCookie removes a cookie by setting its MaxAge to -1.

IMPORTANT: Cookie deletion requires exact matching of the original cookie's attributes (name, domain, path). If the original cookie was set with custom options like WithDomain(), the same options must be provided to DelCookie() for successful deletion.

Parameters:

w: HTTP response writer
r: HTTP request (used for TLS detection)
key: cookie name to delete
opts: optional configuration functions (must match original cookie)

Examples:

hap.DelCookie(w, r, "session")  // Delete basic cookie
hap.DelCookie(w, r, "session", hap.WithDomain(".example.com"))  // Delete with domain

func FixedReplyFields

func FixedReplyFields(args map[string]any)

FixedReplyFields adds fixed fields to JSON reply. For example:

	FixedReplyFields(map[string]any{
	    "version": "1.0.0",
	    "host":    "alpha",
    })

This will add "version" and "host" fields to all JSON replies, which can be used for debugging. Note that if you specify reserved fields like "code", "data" and "mesg", they will not be actually used when producing API reply.

func IsTLS

func IsTLS(r *http.Request, checkProxy bool) bool

IsTLS exposes internal.IsTLS

func JSONMarshaller

func JSONMarshaller() *internal.JSONMarshallerOption

JSONMarshaller returns the JSON Marshaller option object, which is used to customize JSON reply keys in API style replies.

func LoadLanguage

func LoadLanguage(tag language.Tag, trans map[string]string)

LoadLanguage exposes internal.LoadLanguage

func NewSubRequest

func NewSubRequest(parent *http.Request, method, url string, body io.Reader) (*http.Request, error)

NewSubRequest creates a new HTTP request as a child of the parent request, inheriting its tracing context (if present). If the parent contains a TraceContext, the new request will include the Traceparent header for trace continuity. Otherwise, it creates a plain request.

Use this for nested operations (e.g., service-to-service calls) where trace context propagation is required but no additional timeout is needed.

func NewSubRequestWithTimeout

func NewSubRequestWithTimeout(parent *http.Request, timeout time.Duration, method, url string,
	body io.Reader) (req *http.Request, cancel context.CancelFunc, err error)

NewSubRequestWithTimeout creates a child HTTP request with a timeout, inheriting the parent's trace context. If the parent context has no deadline, it applies the given timeout.

The returned cancel function must be called by the caller to release resources, even if the request succeeds:

  • If the parent had no timeout: cancel() stops the sub-request's timer.
  • If the parent had a timeout: cancel() is a no-op but safe to call.

Example:

req, cancel, err := NewSubRequestWithTimeout(parentReq, 5*time.Second, "GET", url, nil)
if err != nil { ... }
defer cancel() // Mandatory to prevent resource leaks
resp, err := http.DefaultClient.Do(req)

func Register

func Register(a API, mx ...*http.ServeMux)

Register registers an API instance. `mx` can be zero or more http.ServeMux instances. If none are provided, the API will be registered with http.DefaultServeMux. In this case, the application only needs to define an http.Server object and call its ListenAndServe method:

svr := http.Server{Addr: ":8080"}
panic(svr.ListenAndServe())

func SetCookie

func SetCookie(w http.ResponseWriter, r *http.Request, key, val string, opts ...CookieOption)

SetCookie creates and sets an HTTP cookie with secure defaults.

The cookie is configured with the following security defaults:

  • HttpOnly: true (prevents JavaScript access)
  • Secure: auto-detected based on request TLS (HTTPS only)
  • SameSite: http.SameSiteLaxMode (CSRF protection)
  • Path: "/" (site-wide availability)

Parameters:

w: HTTP response writer
r: HTTP request (used for TLS detection)
key: cookie name
val: cookie value
opts: optional configuration functions

Examples:

hap.SetCookie(w, r, "session", "token123")  // Basic usage
hap.SetCookie(w, r, "theme", "dark", hap.WithMaxAge(86400))
hap.SetCookie(w, r, "auth", "token", hap.WithDomain(".example.com"), hap.WithMaxAge(3600))

func WithGlobalActions

func WithGlobalActions(as ...Action)

WithGlobalActions defines one or more global actions, which are executed for all HTTP handlers. Global actions are executed before handler specific actions.

func WithLangSpecifier

func WithLangSpecifier(lang string)

WithLangSpecifier exposes internal.WithLangSpecifier

func WithPanicLogger

func WithPanicLogger(f func(mesg string, trace []string))

WithPanicLogger exposes internal.WithPanicLogger

func WithPostResponseTrace

func WithPostResponseTrace(f func(*TraceContext))

WithPostResponseTrace registers a handler function `f` to be executed after the HTTP response is sent to the client.

Key behaviors:

  • The handler `f` is **only invoked** if the request has an associated TraceContextm, and is triggered **after response transmission**.
  • The provided TraceContext in `f` includes the original http.Request object, accessible via TraceContext.Request.
  • The handler runs in the same goroutine as the request, ensure thread safety for shared data. Avoid blocking operations in `f`; use goroutines for long-running tasks.

func WithServiceInfo

func WithServiceInfo(spec ServiceInfo)

WithServiceInfo attaches the given ServiceInfo to the trace context

func WithTraceFlagFunc

func WithTraceFlagFunc(f TraceFlagFunc)

WithTraceFlagFunc registers a decision function to determine the tracing behavior. The provided function should return one of:

  • TraceDisabled (-1): Skip generating Traceparent header
  • TraceNoSample (0): Generate Traceparent with '00' flag (no sampling)
  • TraceSampled (1): Generate Traceparent with '01' flag (sampling enabled)

The registered function will be called during ApiOnEnter phase to evaluate tracing policy for each incoming request.

Types

type API

type API interface {
	Endpoint() string
	Spec(*message.Printer) []ApiSpec
	http.Handler
}

API defines the interface for an API endpoint. The Endpoint() method returns the endpoint path as a string. The Spec() method provides the API specification, formatted using the provided message.Printer.

It also embeds the http.Handler interface, allowing the API to handle HTTP requests.

type Action

type Action func(*arg.Args, http.ResponseWriter, *http.Request) any

Action represents a function signature used for handling HTTP requests within the hap package. It defines a callback function that takes three parameters:

  • *arg.Args: A pointer to the arguments parsed from the request. See the documentation for arg.Args for more details.
  • http.ResponseWriter: An interface used to construct the HTTP response.
  • *http.Request: A pointer to the HTTP request being handled.

The function returns `any`, which allows it to return various types of responses depending on the logic implemented. This type is typically used to define the logic for processing HTTP requests and generating responses based on the request parameters and other conditions.

A handler can define one or more Actions, which are executed sequentially. The output of the previous Action determines whether the next Action will be executed. Although the output of an Action is defined as `any`, it does not mean any type of value can be returned. The allowed return value types and their handling logic are as follows:

  • nil: If an Action returns nil, it indicates that all business logic has been processed and information has been returned to the client. Subsequent Actions will not be executed, and the framework will not return any data to the client.
  • hap.ReplySpec: The Action has completed the business logic and returned the final result. The framework will serialize and send the returned data to the client.
  • error: If the returned type is error, it will be converted to HTTP/500 information and sent to the client.
  • *arg.Args: Indicates that the Action has only processed input parameters or performed part of the business logic. In this case, the next Action will be executed, and the Args parameter passed in will be the result of the previous Action's processing.

func GlobalActions

func GlobalActions() []Action

GlobalActions is called by the framework to get all global actions.

type ApiSpec

type ApiSpec struct {
	Tags     url.Values  `json:"tags,omitempty"`
	Endpoint string      `json:"endpoint"`
	Method   string      `json:"method"`
	Help     []string    `json:"help,omitempty"`
	Params   []ParamSpec `json:"params,omitempty"`
	Output   []ReplyDesc `json:"output,omitempty"`
}

ApiSpec describes the API specification used for documentation.

func Specs

func Specs(endPoint, method string, f *message.Printer) (as []ApiSpec)

Specs is called by [api.ListAPIs] to generate API documentation.

type CookieOption

type CookieOption func(c *http.Cookie)

CookieOption represents a functional option for configuring cookies. It follows the functional options pattern popular in modern Go libraries.

func WithDomain

func WithDomain(domain string) CookieOption

WithDomain sets the cookie's Domain attribute.

The domain determines which hosts can receive the cookie. Use with caution - incorrect domain settings can prevent cookies from being accessible or deleted properly.

Examples:

hap.WithDomain(".example.com")  // Available to all subdomains
hap.WithDomain("api.example.com")  // Only this specific subdomain

Note: Browsers prevent setting cookies for domains other than the current domain or its parent domains for security reasons.

func WithMaxAge

func WithMaxAge(maxAge int) CookieOption

WithMaxAge sets the cookie's MaxAge attribute in seconds.

Positive values: cookie expires after the specified seconds Zero: session cookie (expires when browser closes) Negative: cookie deleted immediately (used by DelCookie)

Example:

hap.WithMaxAge(86400)  // 24 hours
hap.WithMaxAge(0)      // session cookie

type NetRange

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

NetRange represents a collection of network ranges stored in a slice of net.IPNet. This structure is used for access control in HTTP requests.

func NetRangeFunc

func NetRangeFunc(f func() []net.IPNet) *NetRange

NetRangeFunc creates a new NetRange object with a dynamic fetcher function. The key difference between this function and NewNetRange is illustrated in the example below:

func init() {
    hap.Register(api.New("/api/endpoint").WithHandlers{
        handler.GET().WithActions(
            hap.AllowRemoteFrom(true, hap.NetRangeFunc(cfg.SafeNets)),
            handleEndpoint,
        )
    })
}

In this example, the HTTP handlers are defined in the init() function to ensure they are automatically executed. At the time when init() is called, the application's configuration has not yet been initialized. By using NetRangeFunc, the actual network ranges are fetched only when the handler is executed for the first time.

func NewNetRange

func NewNetRange(ipn ...net.IPNet) *NetRange

NewNetRange create a new NetRange object.

func (*NetRange) Add

func (nr *NetRange) Add(ipn ...net.IPNet)

Add appends the provided `ipn` values to the NetRange's slice of net.IPNet.

func (*NetRange) Contains

func (nr *NetRange) Contains(ip net.IP) bool

Contains checks if an IP address is within the NetRange.

func (*NetRange) Get

func (nr *NetRange) Get() []net.IPNet

Get returns the slice of net.IPNet stored within the NetRange.

func (*NetRange) IsTrustedRequest

func (nr *NetRange) IsTrustedRequest(r *http.Request, checkForward bool) bool

IsTrustedRequest checks if an HTTP request `r` comes from an IP address within the NetRange. If `checkForward` is true, the function will check the X-Forwarded-For header (if present); otherwise, it will use r.RemoteAddr. Regardless of the NetRange contents, local loopback addresses (IPv4/IPv6) are always allowed.

In most cases, you should use [WithAccessControl], which internally uses this function.

func (*NetRange) Set

func (nr *NetRange) Set(ipn ...net.IPNet)

Set replaces the NetRange's slice of net.IPNet with the provided `ipn` values.

type ParamSpec

type ParamSpec struct {
	Default  *string    `json:"default,omitempty"`
	Name     string     `json:"name"`
	Type     string     `json:"type"`
	Rules    [][]string `json:"rules,omitempty"`
	Help     []string   `json:"help,omitempty"`
	Required bool       `json:"required"`
}

ParamSpec describes the parameter specification used for documentation.

type ReplyDesc

type ReplyDesc struct {
	Spec ReplySpec `json:"spec"`
	Mime string    `json:"mime"`
	Raw  bool      `json:"raw"`
}

ReplyDesc describes the reply specification used for documentation.

type ReplySpec

type ReplySpec = *internal.Reply

ReplySpec exposes the private 'reply' struct.

func RawReply

func RawReply(code int) ReplySpec

RawReply create a raw reply with an HTTP status code. Unlike the HAP API style Reply, a raw reply allows setting its MIME type using WithMimeType. For example:

func getAvatar(a *arg.Args, w http.ResponseWriter, r *http.Request) any {
	uid := arg.Get[int64](a, "user_id")
	img := getAvatar(uid)
	return hap.RawReply(http.StatusOK).WithData(img).WithMimeType("image/jpeg")
}

func Reply

func Reply(code int) ReplySpec

Reply create a HAP API style reply. The reply will be sent to the client in JSON format, with the following structure:

{
	"code": 200,           // status code must be an integer
	"data": "data",        // data can be any type allowed by JSON
	"mesg": "help message" // help message
}

Among these properties, only `code` is required, while `data` and `mesg` are optional. Typically, `data` is included in successful responses, and `mesg` is used to explain the failure reason in case of an error. The success or failure of the response is indicated by the `code`. A common convention is to use HTTP status codes for `code`. Example:

func setAvatar(a *arg.Args, w http.ResponseWriter, r *http.Request) any {
	uid := arg.Get[int64](a, "user_id")
	err := setAvatar(uid, r.Body)
	if err != nil {
		return hap.Reply(http.StatusInternalServerError).WithHelp(err.Error())
	}
	return hap.Reply(http.StatusOK)
}

type ServiceInfo

type ServiceInfo struct {
	Name    string // service.name
	Address string // service.instance.id
	Version string // service.version
	Environ string // deployment.environment.name
}

ServiceInfo describes the HTTP service, providing information like service name, server IP address, service version, and deployment environment (alpha/beta/stable).

type TraceContext

type TraceContext struct {
	Service      *ServiceInfo
	Attrs        map[string]string
	Request      *http.Request
	Reply        ReplySpec
	Args         *arg.Args
	Route        string //handler matching pattern
	SpanId       string
	SpanName     string
	TraceId      string
	ParentSpanId string

	StartTime int64
	EndTime   int64
	Flags     byte
	// contains filtered or unexported fields
}

TraceContext maps to the W3C TraceContext specification: https://www.w3.org/TR/trace-context/

func ApiOnEnter

func ApiOnEnter(r *http.Request, entry string) *TraceContext

ApiOnEnter is called internally by the framework to create a trace context

func GetTraceContext

func GetTraceContext(r *http.Request) *TraceContext

GetTraceContext returns the trace context from the request context

func (*TraceContext) Attr

func (tc *TraceContext) Attr(key, val string)

Attr adds attributes to the trace context.

func (*TraceContext) End

func (tc *TraceContext) End(fin func(*TraceContext))

func (*TraceContext) GetState

func (tc *TraceContext) GetState(key string) string

func (*TraceContext) Inject

func (tc *TraceContext) Inject(r *http.Request) *http.Request

Inject adds the Traceparent and Tracestate headers to the given HTTP request to propagate distributed tracing context. The headers follow the W3C Trace Context specification. Note: this method does not perform request cloning internally to avoid unnecessary performance overhead in guaranteed-safe scenarios.

func (*TraceContext) NewChild

func (tc *TraceContext) NewChild(name string) *TraceContext

func (*TraceContext) NewRequest

func (tc *TraceContext) NewRequest(ctx context.Context, method, url string, body io.Reader) (*http.Request, error)

NewRequest creates an HTTP request with the provided context, method, URL, and body, and injects the Traceparent and Tracestate headers from the TraceContext to propagate distributed tracing. These headers follow the W3C Trace Context format.

Key behaviors:

  • Traceparent is always injected if the TraceContext is valid.
  • Tracestate is injected only if the TraceContext contains non-empty states.

Usage:

  • Use this method when creating outbound requests that need to participate in a trace.
  • Ensure the context is derived from the parent request's context to maintain cancellation and timeout propagation.
  • If the TraceContext contains vendor-specific states, they will be automatically included in the Tracestate header.

func (*TraceContext) SetState

func (tc *TraceContext) SetState(key, val string) (err error)

func (*TraceContext) TraceState

func (tc *TraceContext) TraceState() string

func (*TraceContext) Traceparent

func (tc *TraceContext) Traceparent() string

Traceparent returns the W3C Traceparent header value for the trace context.

type TraceFlag

type TraceFlag int

func (TraceFlag) String

func (tf TraceFlag) String() string

type TraceFlagFunc

type TraceFlagFunc func(*http.Request) TraceFlag

Source Files

  • actors.go
  • cookie.go
  • ipnet.go
  • json.go
  • proxy.go
  • register.go
  • reply.go
  • request.go
  • sessions.go
  • spec.go
  • state.go
  • trace.go

Directories

Path Synopsis
Package api provides HTTP API endpoint management and specification generation.
Package api provides HTTP API endpoint management and specification generation.
Package arg provides utilities for managing and processing arguments in a structured way.
Package arg provides utilities for managing and processing arguments in a structured way.
Package cors provides configurable handlers for implementing Cross-Origin Resource Sharing (CORS) policies in Go HTTP servers.
Package cors provides configurable handlers for implementing Cross-Origin Resource Sharing (CORS) policies in Go HTTP servers.
Package handler provides HTTP endpoint management and request processing for HAP APIs.
Package handler provides HTTP endpoint management and request processing for HAP APIs.
Package param provides parameter validation utilities with configurable checkers and character sets.
Package param provides parameter validation utilities with configurable checkers and character sets.
Package tag provides functionality for creating and managing Tag objects, which are particularly useful in API documentation.
Package tag provides functionality for creating and managing Tag objects, which are particularly useful in API documentation.

Jump to

Keyboard shortcuts

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