aboutsummaryrefslogtreecommitdiff
path: root/backend/internal/ibd/client.go
diff options
context:
space:
mode:
authorGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-11 13:15:50 -0700
committerGravatar Anshul Gupta <ansg191@anshulg.com> 2024-08-11 13:15:50 -0700
commit6a3c21fb0b1c126849f2bbff494403bbe901448e (patch)
tree5d7805524357c2c8a9819c39d2051a4e3633a1d5 /backend/internal/ibd/client.go
parent29c6040a51616e9e4cf6c70ee16391b2a3b238c9 (diff)
parentf34b92ded11b07f78575ac62c260a380c468e5ea (diff)
downloadibd-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.go97
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
+}