Documentation
¶
Overview ¶
Package http provides functional HTTP client utilities built on top of ReaderIOResult monad. It offers a composable way to make HTTP requests with context support, error handling, and response parsing capabilities. The package follows functional programming principles to ensure type-safe, testable, and maintainable HTTP operations.
The main abstractions include:
- Requester: A reader that constructs HTTP requests with context
- Client: An interface for executing HTTP requests
- Response readers: Functions to parse responses as bytes, text, or JSON
Example usage:
client := MakeClient(http.DefaultClient)
request := MakeGetRequest("https://api.example.com/data")
result := ReadJSON[MyType](client)(request)
response := result(t.Context())()
Index ¶
- Variables
- func ReadAll(client Client) RIOE.Operator[*http.Request, []byte]
- func ReadFullResponse(client Client) RIOE.Operator[*http.Request, H.FullResponse]
- func ReadJSON[A any](client Client) RIOE.Operator[*http.Request, A]
- func ReadJson[A any](client Client) RIOE.Operator[*http.Request, A]deprecated
- func ReadText(client Client) RIOE.Operator[*http.Request, string]
- type Client
- type Requester
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // MakeRequest is an eitherized version of http.NewRequestWithContext. // It creates a Requester that builds an HTTP request with the given method, URL, and body. // This function properly handles errors and wraps them in the Either monad. // // Parameters: // - method: HTTP method (GET, POST, PUT, DELETE, etc.) // - url: The target URL for the request // - body: Optional request body (can be nil) // // Returns: // - A Requester that produces either an error or an *http.Request MakeRequest = RIOE.Eitherize3(http.NewRequestWithContext) // MakeGetRequest creates a GET request for the specified URL. // It's a convenience function that specializes MakeRequest for GET requests with no body. // // Parameters: // - url: The target URL for the GET request // // Returns: // - A Requester that produces either an error or an *http.Request // // Example: // req := MakeGetRequest("https://api.example.com/users") MakeGetRequest = makeRequest("GET", nil) )
Functions ¶
func ReadAll ¶
ReadAll sends an HTTP request and reads the complete response body as a byte array. It validates the HTTP status code and returns the raw response body bytes. This is useful when you need to process the response body in a custom way.
Parameters:
- client: The HTTP client to use for executing the request
Returns:
- A function that takes a Requester and returns a ReaderIOResult[[]byte] containing the response body as bytes
Example:
client := MakeClient(http.DefaultClient)
request := MakeGetRequest("https://api.example.com/data")
readBytes := ReadAll(client)
result := readBytes(request)(t.Context())()
func ReadFullResponse ¶
ReadFullResponse sends an HTTP request and returns both the response and body. It validates the HTTP status code and reads the complete response body into memory.
The returned FullResponse is a Pair containing the http.Response and body bytes, allowing functional access to both components via Response and Body accessors.
Parameters:
- client: The HTTP client to use for executing the request
Returns:
- An Operator that transforms a Requester into a ReaderIOResult producing FullResponse
See Also:
- ReadAll: Extracts only the response body bytes
- ReadText: Extracts the response body as a string
- ReadJSON: Parses the response body as JSON
Example ¶
ExampleReadFullResponse demonstrates basic usage of ReadFullResponse.
package main
import (
"context"
"fmt"
H "net/http"
RIOH "github.com/IBM/fp-go/v2/context/readerioresult/http"
F "github.com/IBM/fp-go/v2/function"
HT "github.com/IBM/fp-go/v2/http"
"github.com/IBM/fp-go/v2/result"
)
func main() {
client := RIOH.MakeClient(H.DefaultClient)
request := RIOH.MakeGetRequest("https://jsonplaceholder.typicode.com/posts/1")
fullResp := RIOH.ReadFullResponse(client)(request)
res := fullResp(context.Background())()
// Extract response and body from the FullResponse pair
statusCode := F.Pipe1(
res,
result.Map(F.Flow2(
HT.Response,
HT.GetStatusCode,
)),
)
fmt.Println(result.IsRight(statusCode))
}
Output: true
Example (AccessingComponents) ¶
ExampleReadFullResponse_accessingComponents demonstrates accessing response components.
package main
import (
"context"
"fmt"
H "net/http"
A "github.com/IBM/fp-go/v2/array"
RIOH "github.com/IBM/fp-go/v2/context/readerioresult/http"
F "github.com/IBM/fp-go/v2/function"
HT "github.com/IBM/fp-go/v2/http"
"github.com/IBM/fp-go/v2/result"
)
func main() {
client := RIOH.MakeClient(H.DefaultClient)
request := RIOH.MakeGetRequest("https://jsonplaceholder.typicode.com/posts/1")
fullResp := RIOH.ReadFullResponse(client)(request)
res := fullResp(context.Background())()
// Access the response metadata
hasContentType := F.Pipe1(
res,
result.Map(F.Flow2(
HT.Response,
func(r *H.Response) bool {
return r.Header.Get("Content-Type") != ""
},
)),
)
// Access the body bytes
hasBody := F.Pipe1(
res,
result.Map(F.Flow2(
HT.Body,
A.IsNonEmpty,
)),
)
fmt.Println(result.IsRight(hasContentType) && result.IsRight(hasBody))
}
Output: true
func ReadJSON ¶
ReadJSON sends an HTTP request, reads the response, and parses it as JSON into type A. It validates both the HTTP status code and the Content-Type header to ensure the response is valid JSON before attempting to unmarshal.
Type Parameters:
- A: The target type to unmarshal the JSON response into
Parameters:
- client: The HTTP client to use for executing the request
Returns:
- A function that takes a Requester and returns a ReaderIOResult[A] containing the parsed JSON data
Example:
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
client := MakeClient(http.DefaultClient)
request := MakeGetRequest("https://api.example.com/user/1")
readUser := ReadJSON[User](client)
result := readUser(request)(t.Context())()
func ReadText ¶
ReadText sends an HTTP request, reads the response body, and converts it to a string. It validates the HTTP status code and returns the response body as a UTF-8 string. This is convenient for APIs that return plain text responses.
Parameters:
- client: The HTTP client to use for executing the request
Returns:
- A function that takes a Requester and returns a ReaderIOResult[string] containing the response body as a string
Example:
client := MakeClient(http.DefaultClient)
request := MakeGetRequest("https://api.example.com/text")
readText := ReadText(client)
result := readText(request)(t.Context())()
Types ¶
type Client ¶
type Client interface {
// Do executes an HTTP request and returns the response wrapped in a ReaderIOResult.
// It takes a Requester (which builds the request) and returns a computation that,
// when executed with a context, performs the HTTP request and returns either
// an error or the HTTP response.
//
// Parameters:
// - req: A Requester that builds the HTTP request
//
// Returns:
// - A ReaderIOResult that produces either an error or an *http.Response
Do(Requester) RIOE.ReaderIOResult[*http.Response]
}
Client is an interface for executing HTTP requests in a functional way. It wraps the standard http.Client and provides a Do method that works with the ReaderIOResult monad for composable, type-safe HTTP operations.
func MakeClient ¶
MakeClient creates a functional HTTP client wrapper around a standard http.Client. The returned Client provides methods for executing HTTP requests in a functional, composable way using the ReaderIOResult monad.
Parameters:
- httpClient: A standard *http.Client to wrap (e.g., http.DefaultClient)
Returns:
- A Client that can execute HTTP requests functionally
Example:
client := MakeClient(http.DefaultClient)
// or with custom client
customClient := &http.Client{Timeout: 10 * time.Second}
client := MakeClient(customClient)
type Requester ¶
type Requester = RIOE.ReaderIOResult[*http.Request]
Requester is a reader that constructs an HTTP request with context support. It represents a computation that, given a context, produces either an error or an HTTP request. This allows for composable request building with proper error handling and context propagation.