diff options
author | 2024-08-11 13:15:50 -0700 | |
---|---|---|
committer | 2024-08-11 13:15:50 -0700 | |
commit | 6a3c21fb0b1c126849f2bbff494403bbe901448e (patch) | |
tree | 5d7805524357c2c8a9819c39d2051a4e3633a1d5 /backend/internal/ibd/client.go | |
parent | 29c6040a51616e9e4cf6c70ee16391b2a3b238c9 (diff) | |
parent | f34b92ded11b07f78575ac62c260a380c468e5ea (diff) | |
download | ibd-trader-6a3c21fb0b1c126849f2bbff494403bbe901448e.tar.gz ibd-trader-6a3c21fb0b1c126849f2bbff494403bbe901448e.tar.zst ibd-trader-6a3c21fb0b1c126849f2bbff494403bbe901448e.zip |
Merge remote-tracking branch 'backend/main'
Diffstat (limited to 'backend/internal/ibd/client.go')
-rw-r--r-- | backend/internal/ibd/client.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/backend/internal/ibd/client.go b/backend/internal/ibd/client.go new file mode 100644 index 0000000..c8575e3 --- /dev/null +++ b/backend/internal/ibd/client.go @@ -0,0 +1,97 @@ +package ibd + +import ( + "context" + "errors" + "log/slog" + "net/http" + "slices" + + "github.com/ansg191/ibd-trader-backend/internal/database" + "github.com/ansg191/ibd-trader-backend/internal/ibd/transport" + "github.com/ansg191/ibd-trader-backend/internal/keys" +) + +var ErrNoAvailableCookies = errors.New("no available cookies") +var ErrNoAvailableTransports = errors.New("no available transports") + +type Client struct { + transports []transport.Transport + db database.Executor + kms keys.KeyManagementService +} + +func NewClient( + db database.Executor, + kms keys.KeyManagementService, + transports ...transport.Transport, +) *Client { + return &Client{transports, db, kms} +} + +func (c *Client) getCookie(ctx context.Context, subject *string) (uint, *http.Cookie, error) { + if subject == nil { + // No subject requirement, get any cookie + cookie, err := database.GetAnyCookie(ctx, c.db, c.kms) + if err != nil { + return 0, nil, err + } + if cookie == nil { + return 0, nil, ErrNoAvailableCookies + } + + return cookie.ID, cookie.ToHTTPCookie(), nil + } + + // Get cookie by subject + cookies, err := database.GetCookies(ctx, c.db, c.kms, *subject, false) + if err != nil { + return 0, nil, err + } + + if len(cookies) == 0 { + return 0, nil, ErrNoAvailableCookies + } + + cookie := cookies[0] + + return cookie.ID, cookie.ToHTTPCookie(), nil +} + +func (c *Client) Do(req *http.Request, opts ...optionFunc) (*http.Response, error) { + o := defaultOptions + for _, opt := range opts { + opt(&o) + } + + // Sort and filter transports by properties + transports := transport.FilterTransports(c.transports, o.requiredProps) + transport.SortTransports(transports) + + for _, tp := range transports { + resp, err := tp.Do(req) + if errors.Is(err, transport.ErrUnsupportedRequest) { + // Skip unsupported transport + continue + } + if err != nil { + slog.ErrorContext(req.Context(), "transport error", + "transport", tp.String(), + "error", err, + ) + continue + } + if slices.Contains(o.expectedStatuses, resp.StatusCode) { + return resp, nil + } else { + slog.ErrorContext(req.Context(), "unexpected status code", + "transport", tp.String(), + "expected", o.expectedStatuses, + "actual", resp.StatusCode, + ) + continue + } + } + + return nil, ErrNoAvailableTransports +} |