Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
  • Loading branch information
bassosimone committed Jun 25, 2024
1 parent 2da0ed8 commit a8de19c
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 55 deletions.
8 changes: 4 additions & 4 deletions internal/httpclientx/baseurl.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ func (e *BaseURL) WithHostOverride(host string) *BaseURL {
// NewBaseURLsFromModelOOAPIServices constructs new [*BaseURL] instances from the
// given [model.OOAPIService] instances, assigning the host header if "cloudfront", and
// skipping all the entries that are neither "https" not "cloudfront".
func NewBaseURLsFromModelOOAPIServices(svcs ...model.OOAPIService) (epnts []*BaseURL) {
func NewBaseURLsFromModelOOAPIServices(svcs ...model.OOAPIService) (bases []*BaseURL) {
for _, svc := range svcs {
epnt := NewBaseURL(svc.Address)
base := NewBaseURL(svc.Address)
switch svc.Type {
case "cloudfront":
epnt = epnt.WithHostOverride(svc.Front)
base = base.WithHostOverride(svc.Front)
fallthrough
case "https":
epnts = append(epnts, epnt)
bases = append(bases, base)
default:
// skip entry
}
Expand Down
12 changes: 6 additions & 6 deletions internal/httpclientx/baseurl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import (

func TestBaseURL(t *testing.T) {
t.Run("the constructor only assigns the URL", func(t *testing.T) {
epnt := NewBaseURL("https://www.example.com/")
if epnt.Value != "https://www.example.com/" {
base := NewBaseURL("https://www.example.com/")
if base.Value != "https://www.example.com/" {
t.Fatal("unexpected URL")
}
if epnt.HostOverride != "" {
if base.HostOverride != "" {
t.Fatal("unexpected host")
}
})

t.Run("we can optionally get a copy with an assigned host header", func(t *testing.T) {
epnt := NewBaseURL("https://www.example.com/").WithHostOverride("www.cloudfront.com")
if epnt.Value != "https://www.example.com/" {
base := NewBaseURL("https://www.example.com/").WithHostOverride("www.cloudfront.com")
if base.Value != "https://www.example.com/" {
t.Fatal("unexpected URL")
}
if epnt.HostOverride != "www.cloudfront.com" {
if base.HostOverride != "www.cloudfront.com" {
t.Fatal("unexpected host")
}
})
Expand Down
10 changes: 5 additions & 5 deletions internal/httpclientx/getjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import (
//
// - ctx is the cancellable context;
//
// - epnt is the HTTP [*BaseURL] to use;
// - base is the HTTP [*BaseURL] to use;
//
// - config contains the config.
//
// This function either returns an error or a valid Output.
func GetJSON[Output any](ctx context.Context, epnt *BaseURL, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedGetJSON[Output](config).Run(ctx, epnt))
func GetJSON[Output any](ctx context.Context, base *BaseURL, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedGetJSON[Output](config).Run(ctx, base))
}

func getJSON[Output any](ctx context.Context, epnt *BaseURL, config *Config) (Output, error) {
func getJSON[Output any](ctx context.Context, base *BaseURL, config *Config) (Output, error) {
// read the raw body
rawrespbody, err := GetRaw(ctx, epnt, config)
rawrespbody, err := GetRaw(ctx, base, config)

// handle the case of error
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions internal/httpclientx/getraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ import (
//
// - ctx is the cancellable context;
//
// - epnt is the HTTP [*BaseURL] to use;
// - base is the HTTP [*BaseURL] to use;
//
// - config is the config to use.
//
// This function either returns an error or a valid Output.
func GetRaw(ctx context.Context, epnt *BaseURL, config *Config) ([]byte, error) {
return OverlappedIgnoreIndex(NewOverlappedGetRaw(config).Run(ctx, epnt))
func GetRaw(ctx context.Context, base *BaseURL, config *Config) ([]byte, error) {
return OverlappedIgnoreIndex(NewOverlappedGetRaw(config).Run(ctx, base))
}

func getRaw(ctx context.Context, epnt *BaseURL, config *Config) ([]byte, error) {
func getRaw(ctx context.Context, base *BaseURL, config *Config) ([]byte, error) {
// construct the request to use
req, err := http.NewRequestWithContext(ctx, "GET", epnt.Value, nil)
req, err := http.NewRequestWithContext(ctx, "GET", base.Value, nil)
if err != nil {
return nil, err
}

// get raw response body
return do(ctx, req, epnt, config)
return do(ctx, req, base, config)
}
10 changes: 5 additions & 5 deletions internal/httpclientx/getxml.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ import (
//
// - ctx is the cancellable context;
//
// - epnt is the HTTP [*BaseURL] to use;
// - base is the HTTP [*BaseURL] to use;
//
// - config is the config to use.
//
// This function either returns an error or a valid Output.
func GetXML[Output any](ctx context.Context, epnt *BaseURL, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedGetXML[Output](config).Run(ctx, epnt))
func GetXML[Output any](ctx context.Context, base *BaseURL, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedGetXML[Output](config).Run(ctx, base))
}

func getXML[Output any](ctx context.Context, epnt *BaseURL, config *Config) (Output, error) {
func getXML[Output any](ctx context.Context, base *BaseURL, config *Config) (Output, error) {
// read the raw body
rawrespbody, err := GetRaw(ctx, epnt, config)
rawrespbody, err := GetRaw(ctx, base, config)

// handle the case of error
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/httpclientx/httpclientx.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func zeroValue[T any]() T {
var ErrTruncated = errors.New("httpapi: truncated response body")

// do is the internal function to finish preparing the request and getting a raw response.
func do(ctx context.Context, req *http.Request, epnt *BaseURL, config *Config) ([]byte, error) {
func do(ctx context.Context, req *http.Request, base *BaseURL, config *Config) ([]byte, error) {
// optionally assign authorization
if value := config.Authorization; value != "" {
req.Header.Set("Authorization", value)
Expand All @@ -56,7 +56,7 @@ func do(ctx context.Context, req *http.Request, epnt *BaseURL, config *Config) (

// OPTIONALLY allow for cloudfronting (the default in net/http is for
// the req.Host to be empty and to use req.URL.Host)
req.Host = epnt.HostOverride
req.Host = base.HostOverride

// get the response
resp, err := config.Client.Do(req)
Expand Down
40 changes: 20 additions & 20 deletions internal/httpclientx/overlapped.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type Overlapped[Output any] struct {
// makes sense for the operation that you requested with the constructor.
//
// If you set it manually, you MUST modify it before calling [*Overlapped.Run].
RunFunc func(ctx context.Context, epnt *BaseURL) (Output, error)
RunFunc func(ctx context.Context, base *BaseURL) (Output, error)

// ScheduleInterval is the MANDATORY scheduling interval.
//
Expand Down Expand Up @@ -65,29 +65,29 @@ func newOverlappedWithFunc[Output any](fx func(context.Context, *BaseURL) (Outpu

// NewOverlappedGetJSON constructs a [*Overlapped] for calling [GetJSON] with multiple URLs.
func NewOverlappedGetJSON[Output any](config *Config) *Overlapped[Output] {
return newOverlappedWithFunc(func(ctx context.Context, epnt *BaseURL) (Output, error) {
return getJSON[Output](ctx, epnt, config)
return newOverlappedWithFunc(func(ctx context.Context, base *BaseURL) (Output, error) {
return getJSON[Output](ctx, base, config)
})
}

// NewOverlappedGetRaw constructs a [*Overlapped] for calling [GetRaw] with multiple URLs.
func NewOverlappedGetRaw(config *Config) *Overlapped[[]byte] {
return newOverlappedWithFunc(func(ctx context.Context, epnt *BaseURL) ([]byte, error) {
return getRaw(ctx, epnt, config)
return newOverlappedWithFunc(func(ctx context.Context, base *BaseURL) ([]byte, error) {
return getRaw(ctx, base, config)
})
}

// NewOverlappedGetXML constructs a [*Overlapped] for calling [GetXML] with multiple URLs.
func NewOverlappedGetXML[Output any](config *Config) *Overlapped[Output] {
return newOverlappedWithFunc(func(ctx context.Context, epnt *BaseURL) (Output, error) {
return getXML[Output](ctx, epnt, config)
return newOverlappedWithFunc(func(ctx context.Context, base *BaseURL) (Output, error) {
return getXML[Output](ctx, base, config)
})
}

// NewOverlappedPostJSON constructs a [*Overlapped] for calling [PostJSON] with multiple URLs.
func NewOverlappedPostJSON[Input, Output any](input Input, config *Config) *Overlapped[Output] {
return newOverlappedWithFunc(func(ctx context.Context, epnt *BaseURL) (Output, error) {
return postJSON[Input, Output](ctx, epnt, input, config)
return newOverlappedWithFunc(func(ctx context.Context, base *BaseURL) (Output, error) {
return postJSON[Input, Output](ctx, base, input, config)
})
}

Expand All @@ -96,8 +96,8 @@ var ErrGenericOverlappedFailure = errors.New("overlapped: generic failure")

// Run runs the overlapped operations, returning the result of the first operation
// that succeeds and its base URL index, or the error that occurred.
func (ovx *Overlapped[Output]) Run(ctx context.Context, epnts ...*BaseURL) (Output, int, error) {
return OverlappedReduce[Output](ovx.Map(ctx, epnts...))
func (ovx *Overlapped[Output]) Run(ctx context.Context, bases ...*BaseURL) (Output, int, error) {
return OverlappedReduce[Output](ovx.Map(ctx, bases...))
}

// OverlappedErrorOr combines error information, result information and the base URL index.
Expand All @@ -112,15 +112,15 @@ type OverlappedErrorOr[Output any] struct {
Value Output
}

// Map applies the [*Overlapped.RunFunc] function to each epnts entry, thus producing
// Map applies the [*Overlapped.RunFunc] function to each bases entry, thus producing
// a result for each entry. This function will cancel subsequent operations until there
// is a success: subsequent results will be [context.Canceled] errors.
//
// Note that you SHOULD use [*Overlapped.Run] unless you want to observe the result
// of each operation, which is mostly useful when running unit tests.
//
// Note that this function will return a zero length slice if epnts lenth is also zero.
func (ovx *Overlapped[Output]) Map(ctx context.Context, epnts ...*BaseURL) []*OverlappedErrorOr[Output] {
// Note that this function will return a zero length slice if bases lenth is also zero.
func (ovx *Overlapped[Output]) Map(ctx context.Context, bases ...*BaseURL) []*OverlappedErrorOr[Output] {
// create cancellable context for early cancellation and also apply the
// watchdog timeout so that eventually this code returns.
//
Expand Down Expand Up @@ -153,12 +153,12 @@ func (ovx *Overlapped[Output]) Map(ctx context.Context, epnts ...*BaseURL) []*Ov
results := []*OverlappedErrorOr[Output]{}

// keep looping until we have results for each base URLs
for len(results) < len(epnts) {
for len(results) < len(bases) {

// if there are more base URLs to try, spawn a goroutine to try,
// and, otherwise, we can safely stop ticking
if idx < len(epnts) {
go ovx.transact(ctx, idx, epnts[idx], output)
if idx < len(bases) {
go ovx.transact(ctx, idx, bases[idx], output)
idx++
} else {
ticker.Stop()
Expand All @@ -170,7 +170,7 @@ func (ovx *Overlapped[Output]) Map(ctx context.Context, epnts ...*BaseURL) []*Ov
// background goroutines and stop ticking
//
// note that we MUST continue reading until we have
// exactly `len(epnts)` results because the inner
// exactly `len(bases)` results because the inner
// goroutine performs blocking writes on the channel
case res := <-output:
results = append(results, res)
Expand Down Expand Up @@ -222,9 +222,9 @@ func OverlappedReduce[Output any](results []*OverlappedErrorOr[Output]) (Output,

// transact performs an HTTP transaction with the given URL and writes results to the output channel.
func (ovx *Overlapped[Output]) transact(
ctx context.Context, idx int, epnt *BaseURL, output chan<- *OverlappedErrorOr[Output]) {
ctx context.Context, idx int, base *BaseURL, output chan<- *OverlappedErrorOr[Output]) {
// obtain the results
value, err := ovx.RunFunc(ctx, epnt)
value, err := ovx.RunFunc(ctx, base)

// emit the results
//
Expand Down
14 changes: 7 additions & 7 deletions internal/httpclientx/postjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ import (
//
// - ctx is the cancellable context;
//
// - epnt is the HTTP [*BaseURL] to use;
// - base is the HTTP [*BaseURL] to use;
//
// - input is the input structure to JSON serialize as the request body;
//
// - config is the config to use.
//
// This function either returns an error or a valid Output.
func PostJSON[Input, Output any](ctx context.Context, epnt *BaseURL, input Input, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedPostJSON[Input, Output](input, config).Run(ctx, epnt))
func PostJSON[Input, Output any](ctx context.Context, base *BaseURL, input Input, config *Config) (Output, error) {
return OverlappedIgnoreIndex(NewOverlappedPostJSON[Input, Output](input, config).Run(ctx, base))
}

func postJSON[Input, Output any](ctx context.Context, epnt *BaseURL, input Input, config *Config) (Output, error) {
func postJSON[Input, Output any](ctx context.Context, base *BaseURL, input Input, config *Config) (Output, error) {
// ensure we're not sending a nil map, pointer, or slice
if _, err := NilSafetyErrorIfNil(input); err != nil {
return zeroValue[Output](), err
Expand All @@ -41,10 +41,10 @@ func postJSON[Input, Output any](ctx context.Context, epnt *BaseURL, input Input
}

// log the raw request body
config.Logger.Debugf("POST %s: raw request body: %s", epnt.Value, string(rawreqbody))
config.Logger.Debugf("POST %s: raw request body: %s", base.Value, string(rawreqbody))

// construct the request to use
req, err := http.NewRequestWithContext(ctx, "POST", epnt.Value, bytes.NewReader(rawreqbody))
req, err := http.NewRequestWithContext(ctx, "POST", base.Value, bytes.NewReader(rawreqbody))
if err != nil {
return zeroValue[Output](), err
}
Expand All @@ -53,7 +53,7 @@ func postJSON[Input, Output any](ctx context.Context, epnt *BaseURL, input Input
req.Header.Set("Content-Type", "application/json")

// get the raw response body
rawrespbody, err := do(ctx, req, epnt, config)
rawrespbody, err := do(ctx, req, base, config)

// handle the case of error
if err != nil {
Expand Down

0 comments on commit a8de19c

Please sign in to comment.