2023-07-14 23:52:14 +02:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
B "github.com/ibm/fp-go/bytes"
|
|
|
|
RIOE "github.com/ibm/fp-go/context/readerioeither"
|
|
|
|
F "github.com/ibm/fp-go/function"
|
2023-07-16 22:46:18 +02:00
|
|
|
H "github.com/ibm/fp-go/http"
|
2023-07-14 23:52:14 +02:00
|
|
|
IOE "github.com/ibm/fp-go/ioeither"
|
|
|
|
IOEF "github.com/ibm/fp-go/ioeither/file"
|
|
|
|
J "github.com/ibm/fp-go/json"
|
2023-07-16 22:46:18 +02:00
|
|
|
T "github.com/ibm/fp-go/tuple"
|
2023-07-14 23:52:14 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// Requester is a reader that constructs a request
|
|
|
|
Requester = RIOE.ReaderIOEither[*http.Request]
|
|
|
|
|
|
|
|
Client interface {
|
|
|
|
// Do can send an HTTP request considering a context
|
|
|
|
Do(Requester) RIOE.ReaderIOEither[*http.Response]
|
|
|
|
}
|
|
|
|
|
|
|
|
client struct {
|
|
|
|
delegate *http.Client
|
|
|
|
doIOE func(*http.Request) IOE.IOEither[error, *http.Response]
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2023-07-17 18:03:21 +02:00
|
|
|
// MakeRequest is an eitherized version of [http.NewRequestWithContext]
|
|
|
|
MakeRequest = RIOE.Eitherize3(http.NewRequestWithContext)
|
|
|
|
makeRequest = F.Bind13of3(MakeRequest)
|
|
|
|
|
|
|
|
// specialize
|
|
|
|
MakeGetRequest = makeRequest("GET", nil)
|
2023-07-14 23:52:14 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func (client client) Do(req Requester) RIOE.ReaderIOEither[*http.Response] {
|
|
|
|
return F.Pipe1(
|
|
|
|
req,
|
|
|
|
RIOE.ChainIOEitherK(client.doIOE),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MakeClient creates an HTTP client proxy
|
|
|
|
func MakeClient(httpClient *http.Client) Client {
|
|
|
|
return client{delegate: httpClient, doIOE: IOE.Eitherize1(httpClient.Do)}
|
|
|
|
}
|
|
|
|
|
2023-07-16 22:46:18 +02:00
|
|
|
// ReadFullResponse sends a request, reads the response as a byte array and represents the result as a tuple
|
|
|
|
func ReadFullResponse(client Client) func(Requester) RIOE.ReaderIOEither[H.FullResponse] {
|
|
|
|
return func(req Requester) RIOE.ReaderIOEither[H.FullResponse] {
|
|
|
|
return F.Flow3(
|
|
|
|
client.Do(req),
|
|
|
|
IOE.ChainEitherK(H.ValidateResponse),
|
|
|
|
IOE.Chain(func(resp *http.Response) IOE.IOEither[error, H.FullResponse] {
|
|
|
|
return F.Pipe1(
|
|
|
|
F.Pipe3(
|
|
|
|
resp,
|
|
|
|
H.GetBody,
|
|
|
|
IOE.Of[error, io.ReadCloser],
|
|
|
|
IOEF.ReadAll[io.ReadCloser],
|
|
|
|
),
|
|
|
|
IOE.Map[error](F.Bind1st(T.MakeTuple2[*http.Response, []byte], resp)),
|
|
|
|
)
|
|
|
|
}),
|
|
|
|
)
|
2023-07-14 23:52:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-17 18:03:21 +02:00
|
|
|
// func test(resp *http.Response) IOE.IOEither[error, H.FullResponse] {
|
|
|
|
// x := F.Pipe3(
|
|
|
|
// resp,
|
|
|
|
// T.Replicate2[*http.Response],
|
|
|
|
// T.Map2(
|
|
|
|
// IOE.Of[error, *http.Response],
|
|
|
|
// F.Flow3(
|
|
|
|
// H.GetBody,
|
|
|
|
// IOE.Of[error, io.ReadCloser],
|
|
|
|
// IOEF.ReadAll[io.ReadCloser],
|
|
|
|
// ),
|
|
|
|
// ),
|
|
|
|
// )
|
|
|
|
// }
|
|
|
|
|
2023-07-16 22:46:18 +02:00
|
|
|
// ReadAll sends a request and reads the response as bytes
|
|
|
|
func ReadAll(client Client) func(Requester) RIOE.ReaderIOEither[[]byte] {
|
|
|
|
return F.Flow2(
|
|
|
|
ReadFullResponse(client),
|
|
|
|
RIOE.Map(H.Body),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-07-14 23:52:14 +02:00
|
|
|
// ReadText sends a request, reads the response and represents the response as a text string
|
|
|
|
func ReadText(client Client) func(Requester) RIOE.ReaderIOEither[string] {
|
|
|
|
return F.Flow2(
|
|
|
|
ReadAll(client),
|
|
|
|
RIOE.Map(B.ToString),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadJson sends a request, reads the response and parses the response as JSON
|
|
|
|
func ReadJson[A any](client Client) func(Requester) RIOE.ReaderIOEither[A] {
|
2023-07-16 22:46:18 +02:00
|
|
|
return F.Flow3(
|
|
|
|
ReadFullResponse(client),
|
|
|
|
RIOE.ChainFirstEitherK(F.Flow2(
|
|
|
|
H.Response,
|
|
|
|
H.ValidateJsonResponse,
|
|
|
|
)),
|
|
|
|
RIOE.ChainEitherK(F.Flow2(
|
|
|
|
H.Body,
|
|
|
|
J.Unmarshal[A],
|
|
|
|
)),
|
2023-07-14 23:52:14 +02:00
|
|
|
)
|
|
|
|
}
|