hureg

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2024 License: MIT Imports: 10 Imported by: 1

README

Go Reference list list

hureg logo

HUMA is a great Go framework that enables you to expose generated OpenAPI spec in the best way possible. Unfortunately, it lacks some features from other routers.

This library wraps HUMA framework endpoints registration pipeline to provide the missing features:

❤️ Create registration groups

Similar to other routers you can create a derived api (i.e. group) that has pre-defined:

  • Base path (same as Group, Route methods in other routers)
  • Multiple alternative base paths
  • Middlewares
    • including a trick to use router-specific middlewares for a group
  • Transformers
  • Tags and other Huma Operation properties that will be applied to all endpoints in a group.
  • Control the registration pipeline preventing operation from registration or registering it multiple times with different properties

❤️ Control over OpenAPI endpoints

Now you have manual control over exposing the spec, docs and schemas:

  • Expose only needed spec versions
  • Add own middlewares (e.g. authentication to protect the spec on public APIs)
  • Have separate scoped OpenAPI specs for different parts of your API

❤️ Access more metadata in Operation Handlers

The library provides additional information via Metadata field to your own Operation Handlers:

  • Input/Output types of a handler
  • OpenAPI object from huma.API instance
  • Whether an operation was defined explicitly or implicitly via convenience methods
  • etc.

Installation

go get github.com/cardinalby/hureg

Documentation

Key concepts

Common use-cases

Additional features

Examples

🔻 Initialization

import "github.com/cardinalby/hureg"

httpServeMux := http.NewServeMux()              // with go 1.22
cfg := huma.DefaultConfig("My API", "1.0.0")    // default HUMA initialization
humaApi := humago.New(httpServeMux, cfg)        // --

api := hureg.NewAPIGen(humaApi)    // The new line

🔻 "Base path + tags + middlewares" group

v1gr := api.            // all operations registered with v1gr will have:
	AddBasePath("/v1").                            // - "/v1" base path
	AddOpHandler(op_handler.AddTags("some_tag")).  // - "some_tag" tag
	AddMiddlewares(m1, m2)                         // - m1, m2 middlewares
	
hureg.Get(v1gr, "/cat", ...) // "/v1/cat" with "some_tag" tag and m1, m2 middlewares
hureg.Get(v1gr, "/dog", ...) // "/v1/dog" with "some_tag" tag and m1, m2 middlewares

🔻 Multiple base paths

Sometimes we need to register the same endpoint with multiple base paths (e.g. /v1 and /v2).

multiPathGr := api.AddMultiBasePaths(nil, "/v1", "/v2")

hureg.Get(multiPathGr, "/sparrow", ...) // "/v1/sparrow"
                                        // "/v2/sparrow"

🔻 Transformers per group

trGr := api.AddTransformers(...) // transformers will be applied only to the operations 
                                 // registered in this group

hureg.Get(trGr, "/crocodile", ...)

🔻 Complete server setup

Check out integration_test.go for a complete example of how to use the library:

  • create huma.API from http.ServeMux router
  • create APIGen instance on top of huma.API
  • register operations with APIGen instance
    • use base paths, tags and Transformers to the groups
    • register OpenAPI endpoints manually with Basic Auth middleware

Uncommenting one line you can run the server and play with it in live mode.

Go version

Even though Huma declares Go 1.20 as the minimal supported version, it actually requires Go 1.22 for correct work due to "slices" package usage. So hureg requires Go 1.22 explicitly.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Delete

func Delete[I, O any](
	api API,
	path string,
	handler func(
		context.Context,
		*I,
	) (*O, error), operationHandlers ...func(o *huma.Operation))

Delete is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Get

func Get[I, O any](
	api API,
	path string,
	handler func(context.Context, *I) (*O, error),
	operationHandlers ...func(o *huma.Operation),
)

Get is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Head[I, O any](
	api API,
	path string,
	handler func(
		context.Context,
		*I,
	) (*O, error), operationHandlers ...func(o *huma.Operation))

Head is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Options

func Options[I, O any](
	api API,
	path string,
	handler func(
		context.Context,
		*I,
	) (*O, error), operationHandlers ...func(o *huma.Operation))

Options is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Patch

func Patch[I, O any](
	api API,
	path string,
	handler func(context.Context, *I) (*O, error),
	operationHandlers ...func(o *huma.Operation),
)

Patch is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Post

func Post[I, O any](
	api API,
	path string,
	handler func(context.Context, *I) (*O, error),
	operationHandlers ...func(o *huma.Operation),
)

Post is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Put

func Put[I, O any](
	api API,
	path string,
	handler func(context.Context, *I) (*O, error),
	operationHandlers ...func(o *huma.Operation),
)

Put is a shortcut for Register method that implicitly generates Operation object metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will not be set.

func Register

func Register[I, O any](
	api API,
	operation huma.Operation,
	handler func(context.Context, *I) (*O, error),
	operationHandlers ...func(o *huma.Operation),
)

Register registers a handler for an explicitly provided operation. It will apply all RegMiddlewares stored in API to the operation and passed operationHandlers after that. Depending on RegMiddlewares, an operation can be modified, registered multiple times with different base paths or not registered at all. Before passing an operation to the RegMiddlewares, it will be initialized with the metadata keys required for the library functionality. metadata.KeyIsExplicitOperationID, metadata.KeyIsExplicitSummary keys will be set to `true` See other keys in metadata package for details.

Types

type API

type API interface {
	GetHumaAPI() huma.API
	GetExtraHumaAPIs() []ExtraHumaApiInstance
	GetRegMiddlewares() RegMiddlewares
	GetBubblingRegMiddlewares() RegMiddlewares
	GetTransformers() []huma.Transformer
}

API is wrapper of huma.API that stores RegMiddlewares that should be applied to operations before registration in Huma.

type APIGen

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

APIGen is a core type of the library that wraps huma.API and stores RegMiddlewares that should be applied to operations before registration in Huma. It provides a fluent API to create derived APIGen instances with own set of actions/changes to an operation before its registration.

func NewAPIGen

func NewAPIGen(humaApi huma.API) APIGen

NewAPIGen creates a new APIGen instance with the given huma.API.

func (APIGen) AddBasePath

func (a APIGen) AddBasePath(basePath string) APIGen

AddBasePath returns a new APIGen instance that will add the given basePath segment to an operation`s Path. It will append `basePath` to the previously added base paths if any. Adding a base path also re-generates the OperationID and Summary fields of an operation if it wasn't explicitly set. It's an alternative to Route, Group methods of go routes.

func (APIGen) AddBubblingRegMiddleware added in v1.0.0

func (a APIGen) AddBubblingRegMiddleware(regMiddlewares ...RegMiddleware) APIGen

AddBubblingRegMiddleware returns a new APIGen instance with the given RegMiddlewares added to the stored bubbling RegMiddlewares. Bubbling RegMiddlewares will be applied to the operation in the opposite order after normal RegMiddlewares are done allowing you to observe changes made by all previous RegMiddlewares.

func (APIGen) AddExtraHumaAPI added in v1.0.0

func (a APIGen) AddExtraHumaAPI(api huma.API, bubblingRegMiddlewares ...RegMiddleware) APIGen

AddExtraHumaAPI returns a new APIGen instance with the given huma.API added to the extraHumaAPIs. All operations registered with this APIGen instance or derived instances will be passed to the given `api` additionally to the main huma.API. Optional bubbling RegMiddlewares will be applied to the operations before the registration in the `api`.

func (APIGen) AddMiddlewares

func (a APIGen) AddMiddlewares(middlewares ...func(huma.Context, func(huma.Context))) APIGen

AddMiddlewares returns a new APIGen instance that will add the given middlewares to the operation.

func (APIGen) AddMultiBasePaths

func (a APIGen) AddMultiBasePaths(
	explicitOpIDBuilder func(*huma.Operation) string,
	basePaths ...string,
) APIGen

AddMultiBasePaths returns a new APIGen instance that will register the same operation with multiple base paths. It respects base paths added before and after this method call. Since it leads to multiple registrations of the same operation, it requires OperationID to be updated to avoid registration of multiple operations with the same OperationID. If an operation has generated OperationID, it will be re-generated by default Huma operation ID builder. The same is true for the Summary field. For the case of explicitly set OperationID, you can provide a custom `explicitOpIDBuilder` builder. It will receive an operation with modified Path and metadata.KeyBasePath and should return a new OperationID. If `explicitOpIDBuilder` is nil, the built-in approach will be used. It will take metadata.KeyBasePath as a prefix for the OperationID, turning it into kebab-case and will append it to the metadata.KeyInitOperationID (that stores the initial user-provided OperationID).

func (APIGen) AddOpHandler

func (a APIGen) AddOpHandler(handlers ...op_handler.OperationHandler) APIGen

AddOpHandler returns a new APIGen instance with the given OperationHandlers added to it.

func (APIGen) AddOwnOpenAPI added in v1.0.0

func (a APIGen) AddOwnOpenAPI(apiConfig huma.Config, bubblingRegMiddlewares ...RegMiddleware) (APIGen, *huma.OpenAPI)

AddOwnOpenAPI is a shortcut function to create a new APIGen instance and a OpenAPI object instance together. All operations registered with this APIGen instance or derived instances will be added to the OpenAPI object. `bubbleRegMiddlewares` will be additionally applied to the operations before the registration in the OpenAPI object. It allows you to have separate OpenAPI spec that contains only operations registered with this APIGen instance or derived instances. Use it in combination with `pkg/huma/oapi_handlers` package to serve the created OpenAPI spec.

func (APIGen) AddRegMiddleware

func (a APIGen) AddRegMiddleware(regMiddlewares ...RegMiddleware) APIGen

AddRegMiddleware returns a new APIGen instance with the given RegMiddlewares added to the stored RegMiddlewares.

func (APIGen) AddTransformers

func (a APIGen) AddTransformers(transformers ...huma.Transformer) APIGen

AddTransformers returns a new APIGen instance with the given transformers that will be applied to the responses of the handlers registered by this APIGen.

func (APIGen) GetBubblingRegMiddlewares added in v1.0.0

func (a APIGen) GetBubblingRegMiddlewares() RegMiddlewares

GetBubblingRegMiddlewares returns the stored bubbling RegMiddlewares.

func (APIGen) GetExtraHumaAPIs added in v1.0.0

func (a APIGen) GetExtraHumaAPIs() []ExtraHumaApiInstance

GetExtraHumaAPIs returns the stored extraHumaAPIs.

func (APIGen) GetHumaAPI

func (a APIGen) GetHumaAPI() huma.API

GetHumaAPI returns the wrapped huma.API.

func (APIGen) GetRegMiddlewares

func (a APIGen) GetRegMiddlewares() RegMiddlewares

GetRegMiddlewares returns the stored RegMiddlewares.

func (APIGen) GetTransformers

func (a APIGen) GetTransformers() []huma.Transformer

GetTransformers returns the stored transformers that will be applied to the responses of the handlers registered by this APIGen.

func (APIGen) ReplaceHumaAPI added in v1.0.2

func (a APIGen) ReplaceHumaAPI(humaApi huma.API) APIGen

ReplaceHumaAPI returns a new APIGen instance with replaced huma.API pointer. Can be useful for some tricky cases when you create huma.API instance based on another adapter but with the same config (and OpenAPI object pointer) to utilize router-specific middlewares for a group.

type ExtraHumaApiInstance added in v1.0.1

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

type RegMiddleware

type RegMiddleware func(op huma.Operation, next func(huma.Operation))

RegMiddleware is core concept of the library that provides flexibility in setting up the registration pipeline: using route groups, pre-specified middlewares and other properties of operations for an instance of API RegMiddlewares are functions that are called in chain (similar to normal HTTP middlewares) during the operation registration (before the operation will be registered in Huma). RegMiddleware can produce side effects or modify the operation and pass it to the next RegMiddleware in the chain. - Calling `next` more than one time will lead to multiple registrations of the same operation, see RegMiddlewares.FanOut method - By not calling `next` at all you can prevent the operation from being registered

func NewRegMiddleware

func NewRegMiddleware(opHandlers ...op_handler.OperationHandler) RegMiddleware

NewRegMiddleware creates a new RegMiddleware that applies the given OperationHandlers to the operation.

type RegMiddlewares

type RegMiddlewares []RegMiddleware

func (RegMiddlewares) Chain

func (hs RegMiddlewares) Chain() RegMiddleware

Chain creates a new RegMiddleware that chains RegMiddlewares together returning a single RegMiddleware.

func (RegMiddlewares) FanOut

func (hs RegMiddlewares) FanOut() RegMiddleware

FanOut creates a new RegMiddleware that calls all RegMiddlewares one by one passing the same `next` function to them and a copy of the received operation. It leads to "multiplication" of the registration pipeline, creating multiple branches of registration pipeline after this RegMiddleware. It can be used to register multiple operations in Huma out of one registration call. Normally you are not supposed to use it in your own registration pipelines since:

  • it requires a special handling of OperationID in order not to get multiple operations with the same OperationID
  • it uses internal operation cloning that is sufficient for the library-provided operation handlers but may not be sufficient for your custom operation handlers that modify the nested structures of the operation.

It's used to create multiple alternative base paths for the same operation.

func (RegMiddlewares) Handler

func (hs RegMiddlewares) Handler(registerer func(huma.Operation)) func(huma.Operation)

Handler creates a final function that accepts Operation, passes it to the chain of RegMiddlewares and then to the provided registerer function.

Jump to

Keyboard shortcuts

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