builder

package
v2.3.137 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package builder provides a functional, immutable HTTP request builder with composable operations. It follows functional programming principles to construct HTTP requests in a type-safe, testable, and maintainable way.

The Builder type is immutable - all operations return a new builder instance rather than modifying the existing one. This ensures thread-safety and makes the code easier to reason about.

Key Features:

  • Immutable builder pattern with method chaining
  • Lens-based access to builder properties
  • Support for headers, query parameters, request body, and HTTP methods
  • JSON and form data encoding
  • URL construction with query parameter merging
  • Hash generation for caching
  • Bearer token authentication helpers

Basic Usage:

import (
    B "github.com/IBM/fp-go/v2/http/builder"
    F "github.com/IBM/fp-go/v2/function"
)

// Build a simple GET request
builder := F.Pipe2(
    B.Default,
    B.WithURL("https://api.example.com/users"),
    B.WithHeader("Accept")("application/json"),
)

// Build a POST request with JSON body
builder := F.Pipe3(
    B.Default,
    B.WithURL("https://api.example.com/users"),
    B.WithMethod("POST"),
    B.WithJSON(map[string]string{"name": "John"}),
)

// Build a request with query parameters
builder := F.Pipe3(
    B.Default,
    B.WithURL("https://api.example.com/search"),
    B.WithQueryArg("q")("golang"),
    B.WithQueryArg("limit")("10"),
)

The package provides several convenience functions for common HTTP methods:

  • WithGet, WithPost, WithPut, WithDelete for setting HTTP methods
  • WithBearer for adding Bearer token authentication
  • WithJSON for JSON payloads
  • WithFormData for form-encoded payloads

Lenses are provided for advanced use cases:

  • URL, Method, Body, Headers, Query for accessing builder properties
  • Header(name) for accessing individual headers
  • QueryArg(name) for accessing individual query parameters

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Default is the default builder
	Default = &Builder{method: O.Some(defaultMethod()), headers: make(http.Header), body: noBody}

	// Monoid is the [M.Monoid] for the [Endomorphism]
	Monoid = ENDO.Monoid[*Builder]()

	// Url is a [Lens] for the URL
	//
	// Deprecated: use [URL] instead
	Url = L.MakeLensRef((*Builder).GetURL, (*Builder).SetURL)
	// URL is a [Lens] for the URL
	URL = L.MakeLensRef((*Builder).GetURL, (*Builder).SetURL)
	// Method is a [Lens] for the HTTP method
	Method = L.MakeLensRef((*Builder).GetMethod, (*Builder).SetMethod)
	// Body is a [Lens] for the request body
	Body = L.MakeLensRef((*Builder).GetBody, (*Builder).SetBody)
	// Headers is a [Lens] for the complete set of request headers
	Headers = L.MakeLensRef((*Builder).GetHeaders, (*Builder).SetHeaders)
	// Query is a [Lens] for the set of query parameters
	Query = L.MakeLensRef((*Builder).GetQuery, (*Builder).SetQuery)

	// WithQuery creates a [Endomorphism] for a complete set of query parameters
	WithQuery = Query.Set
	// WithMethod creates a [Endomorphism] for a certain method
	WithMethod = Method.Set
	// WithUrl creates a [Endomorphism] for the URL
	//
	// Deprecated: use [WithURL] instead
	WithUrl = URL.Set
	// WithURL creates a [Endomorphism] for the URL
	WithURL = URL.Set
	// WithHeaders creates a [Endomorphism] for a set of headers
	WithHeaders = Headers.Set
	// WithBody creates a [Endomorphism] for a request body
	WithBody = F.Flow2(
		O.Of[Result[[]byte]],
		Body.Set,
	)
	// WithBytes creates a [Endomorphism] for a request body using bytes
	WithBytes = F.Flow2(
		result.Of[[]byte],
		WithBody,
	)
	// WithContentType adds the [H.ContentType] header
	WithContentType = WithHeader(H.ContentType)
	// WithAuthorization adds the [H.Authorization] header
	WithAuthorization = WithHeader(H.Authorization)

	// WithGet adds the [http.MethodGet] method
	WithGet = WithMethod(http.MethodGet)
	// WithPost adds the [http.MethodPost] method
	WithPost = WithMethod(http.MethodPost)
	// WithPut adds the [http.MethodPut] method
	WithPut = WithMethod(http.MethodPut)
	// WithDelete adds the [http.MethodDelete] method
	WithDelete = WithMethod(http.MethodDelete)

	// WithBearer creates a [Endomorphism] to add a Bearer [H.Authorization] header
	WithBearer = F.Flow2(
		S.Format[string]("Bearer %s"),
		WithAuthorization,
	)

	// WithoutBody creates a [Endomorphism] to remove the body
	WithoutBody = F.Pipe1(
		noBody,
		Body.Set,
	)

	// WithFormData creates a [Endomorphism] to send form data payload
	WithFormData = F.Flow4(
		url.Values.Encode,
		S.ToBytes,
		WithBytes,
		withFormContentType,
	)
)

Functions

func MakeHash

func MakeHash(b *Builder) string

MakeHash converts a Builder into a hash string, convenient to use as a cache key

Example

ExampleMakeHash demonstrates the cache key of a builder. It only depends on the content of the request, not on the order in which the builder was assembled.

b1 := F.Pipe2(
	Default,
	WithURL("https://api.example.com/users"),
	WithContentType(C.JSON),
)

b2 := F.Pipe2(
	Default,
	WithContentType(C.JSON),
	WithURL("https://api.example.com/users"),
)

fmt.Println(MakeHash(b1) == MakeHash(b2))
fmt.Println(MakeHash(b1) == MakeHash(Default))
Output:
true
false

func WithHeader

func WithHeader(name string) func(value string) Endomorphism

WithHeader creates a Endomorphism for a certain header

func WithQueryArg

func WithQueryArg(name string) func(value string) Endomorphism

WithQueryArg creates a Endomorphism for a certain query argument

Types

type Builder

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

func (*Builder) DelHeader

func (builder *Builder) DelHeader(name string) *Builder

func (*Builder) GetBody

func (builder *Builder) GetBody() Option[Result[[]byte]]

func (*Builder) GetHash

func (builder *Builder) GetHash() string

GetHash returns a hash value for the builder that can be used as a cache key

func (*Builder) GetHeader

func (builder *Builder) GetHeader(name string) Option[string]

func (*Builder) GetHeaderValues

func (builder *Builder) GetHeaderValues(name string) []string

func (*Builder) GetHeaders

func (builder *Builder) GetHeaders() http.Header

func (*Builder) GetMethod

func (builder *Builder) GetMethod() string

func (*Builder) GetQuery

func (builder *Builder) GetQuery() url.Values

func (*Builder) GetTargetURL

func (builder *Builder) GetTargetURL() Result[string]

GetTargetURL constructs a full URL with query parameters on top of the provided URL string

Example

ExampleBuilder_GetTargetURL demonstrates that the query parameters of the builder are merged into the query parameters already present in the URL

b := F.Pipe3(
	Default,
	WithURL("https://api.example.com/search?lang=en"),
	WithQueryArg("q")("golang"),
	WithQueryArg("limit")("10"),
)

fmt.Println(renderTarget(b))
Output:
https://api.example.com/search?lang=en&limit=10&q=golang
Example (Invalid)

ExampleBuilder_GetTargetURL_invalid demonstrates that an unparseable URL surfaces as an error rather than as a panic

fmt.Println(renderTarget(F.Pipe1(Default, WithURL("://not-a-url"))))
Output:
parse "://not-a-url": missing protocol scheme

func (*Builder) GetTargetUrl deprecated

func (builder *Builder) GetTargetUrl() Result[string]

GetTargetUrl constructs a full URL with query parameters on top of the provided URL string

Deprecated: use [GetTargetURL] instead

func (*Builder) GetURL

func (builder *Builder) GetURL() string

func (*Builder) GetUrl deprecated

func (builder *Builder) GetUrl() string

Deprecated: use [GetURL] instead

func (*Builder) SetBody

func (builder *Builder) SetBody(body Option[Result[[]byte]]) *Builder

func (*Builder) SetHeader

func (builder *Builder) SetHeader(name, value string) *Builder

func (*Builder) SetHeaders

func (builder *Builder) SetHeaders(headers http.Header) *Builder

func (*Builder) SetMethod

func (builder *Builder) SetMethod(method string) *Builder

func (*Builder) SetQuery

func (builder *Builder) SetQuery(query url.Values) *Builder

func (*Builder) SetURL

func (builder *Builder) SetURL(url string) *Builder

func (*Builder) SetUrl deprecated

func (builder *Builder) SetUrl(url string) *Builder

Deprecated: use [SetURL] instead

type Endomorphism

type Endomorphism = ENDO.Endomorphism[*Builder]

Endomorphism returns an [ENDO.Endomorphism] that transforms a builder

func WithJSON

func WithJSON[T any](data T) Endomorphism

WithJSON creates a Endomorphism to send JSON payload

Example

ExampleWithJSON demonstrates a JSON payload, which also sets the content type

b := F.Pipe3(
	Default,
	WithURL("https://api.example.com/users"),
	WithPost,
	WithJSON(map[string]string{"name": "John"}),
)

fmt.Println(b.GetMethod())
fmt.Println(b.GetHeader(H.ContentType))
fmt.Println(renderBody(b))
Output:
POST
Some[string](application/json)
{"name":"John"}

func WithJson deprecated

func WithJson[T any](data T) Endomorphism

WithJson creates a Endomorphism to send JSON payload

Deprecated: use WithJSON instead

func WithoutHeader

func WithoutHeader(name string) Endomorphism

WithoutHeader creates a Endomorphism to remove a certain header

func WithoutQueryArg

func WithoutQueryArg(name string) Endomorphism

WithoutQueryArg creates a Endomorphism that removes a query argument

type Lens

type Lens[S, T any] = common.Lens[S, T]
func Header(name string) Lens[*Builder, Option[string]]

Header returns a Lens for a single header

Example

ExampleHeader demonstrates the Lens for a single header. Setting the focus to none removes the header, the source builder is never modified.

accept := Header(H.Accept)

withJSON := F.Pipe1(Default, accept.Set(O.Of(C.JSON)))
without := F.Pipe1(withJSON, accept.Set(O.None[string]()))

fmt.Println(accept)
fmt.Println(accept.Get(withJSON))
fmt.Println(accept.Get(without))
fmt.Println(accept.Get(Default))
Output:
HttpHeader[Accept]
Some[string](application/json)
None[string]
None[string]

func QueryArg

func QueryArg(name string) Lens[*Builder, Option[string]]

QueryArg is a Lens for the first value of a query argument

Example

ExampleQueryArg demonstrates the Lens for a single query parameter

limit := QueryArg("limit")

b := F.Pipe2(
	Default,
	WithURL("https://api.example.com/users"),
	limit.Set(O.Of("10")),
)

fmt.Println(limit.Get(b))
fmt.Println(renderTarget(b))
fmt.Println(renderTarget(F.Pipe1(b, limit.Set(O.None[string]()))))
Output:
Some[string](10)
https://api.example.com/users?limit=10
https://api.example.com/users

type Option

type Option[T any] = option.Option[T]

type Result

type Result[T any] = result.Result[T]

Jump to

Keyboard shortcuts

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