feat(options): Add CustomEndpoint and customHeaders clientOptions

This commit is contained in:
Matthieu 'JP' DERASSE 2023-08-12 20:00:35 +00:00
parent a5bf04816e
commit 73aa82a79b
Signed by: mderasse
GPG Key ID: 55141C777B16A705
6 changed files with 49 additions and 11 deletions

View File

@ -26,9 +26,11 @@ type Client struct {
HTTPClient HTTPClient HTTPClient HTTPClient
userAgent string userAgent string
endpoint string
headers map[string]string
} }
// NewClient create a new tesla-stock client with default HTTP Client. // NewClient create a new tesla-inventory client with default HTTP Client.
func NewClient(options ...ClientOptions) *Client { func NewClient(options ...ClientOptions) *Client {
client := Client{ client := Client{
@ -36,6 +38,7 @@ func NewClient(options ...ClientOptions) *Client {
lastRequest: &atomic.Value{}, lastRequest: &atomic.Value{},
lastResponse: &atomic.Value{}, lastResponse: &atomic.Value{},
HTTPClient: http.DefaultClient, HTTPClient: http.DefaultClient,
endpoint: inventoryApiEndpoint,
userAgent: defaultUserAgent, userAgent: defaultUserAgent,
} }
@ -120,6 +123,7 @@ func (c *Client) LastAPIResponse() (*http.Response, bool) {
return nil, false return nil, false
} }
//nolint:unused // keeping to respect classical http verb.
func (c *Client) delete(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) { func (c *Client) delete(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) {
if payload != nil { if payload != nil {
data, err := json.Marshal(payload) data, err := json.Marshal(payload)
@ -131,6 +135,7 @@ func (c *Client) delete(ctx context.Context, path string, payload interface{}, h
return c.do(ctx, http.MethodDelete, path, nil, headers) return c.do(ctx, http.MethodDelete, path, nil, headers)
} }
//nolint:unused // keeping to respect classical http verb.
func (c *Client) put(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) { func (c *Client) put(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) {
if payload != nil { if payload != nil {
data, err := json.Marshal(payload) data, err := json.Marshal(payload)
@ -142,6 +147,7 @@ func (c *Client) put(ctx context.Context, path string, payload interface{}, head
return c.do(ctx, http.MethodPut, path, nil, headers) return c.do(ctx, http.MethodPut, path, nil, headers)
} }
//nolint:unused // keeping to respect classical http verb.
func (c *Client) post(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) { func (c *Client) post(ctx context.Context, path string, payload interface{}, headers map[string]string) (*http.Response, error) {
data, err := json.Marshal(payload) data, err := json.Marshal(payload)
if err != nil { if err != nil {
@ -172,7 +178,8 @@ func dupeRequest(r *http.Request) (*http.Request, error) {
return dreq, nil return dreq, nil
} }
func (c *Client) Do(r *http.Request, authRequired bool) (*http.Response, error) { // Do allow anyone to extend sdk.
func (c *Client) Do(r *http.Request) (*http.Response, error) {
c.prepareRequest(r, nil) c.prepareRequest(r, nil)
return c.HTTPClient.Do(r) return c.HTTPClient.Do(r)
@ -197,7 +204,7 @@ func (c *Client) do(ctx context.Context, method, path string, body io.Reader, he
}() }()
} }
req, err := http.NewRequestWithContext(ctx, method, stockApiEndpoint+path, body) req, err := http.NewRequestWithContext(ctx, method, c.endpoint+path, body)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to build request: %w", err) return nil, fmt.Errorf("failed to build request: %w", err)
} }
@ -217,6 +224,12 @@ func (c *Client) do(ctx context.Context, method, path string, body io.Reader, he
} }
func (c *Client) prepareRequest(req *http.Request, headers map[string]string) { func (c *Client) prepareRequest(req *http.Request, headers map[string]string) {
// set permanent headers provided at the creation of the client
for k, v := range c.headers {
req.Header.Set(k, v)
}
// adding / overiding headers those set for this request
for k, v := range headers { for k, v := range headers {
req.Header.Set(k, v) req.Header.Set(k, v)
} }
@ -229,7 +242,7 @@ func (c *Client) checkResponse(resp *http.Response, err error) (*http.Response,
return resp, fmt.Errorf("error calling the API endpoint: %w", err) return resp, fmt.Errorf("error calling the API endpoint: %w", err)
} }
// Stock API always return a 200 // Inventory API always return a 200
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return resp, c.getErrorFromResponse(resp) return resp, c.getErrorFromResponse(resp)
} }

View File

@ -9,3 +9,17 @@ func WithUserAgent(userAgent string) ClientOptions {
c.userAgent = userAgent c.userAgent = userAgent
} }
} }
// WithCustomEndpoint will allow to overide the default endpoint with a custom one.
func WithCustomEndpoint(endpoint string) ClientOptions {
return func(c *Client) {
c.endpoint = endpoint
}
}
// WithHeaders will add the given headers to every request made by the sdk.
func WithHeaders(headers map[string]string) ClientOptions {
return func(c *Client) {
c.headers = headers
}
}

View File

@ -2,9 +2,9 @@ package teslainventory_sdk
const ( const (
// Version is the current version of the sdk. // Version is the current version of the sdk.
Version = "1.0.0" Version = "1.0.0"
stockApiEndpoint = "https://www.tesla.com/" inventoryApiEndpoint = "https://www.tesla.com/inventory/api/"
defaultUserAgent = "TeslaApp/" + Version defaultUserAgent = "TeslaApp/" + Version
) )
// DebugFlag represents a set of debug bit flags that can be bitwise-ORed // DebugFlag represents a set of debug bit flags that can be bitwise-ORed

2
go.mod
View File

@ -1,3 +1,3 @@
module git.dev.m-and-m.ovh/mderasse/teslainventory_sdk module git.dev.m-and-m.ovh/mderasse/teslainventory_sdk
go 1.21 go 1.21.0

View File

@ -8,7 +8,7 @@ import (
) )
// GetAvailabilities return the car availabilities matching with the provided characteristics. // GetAvailabilities return the car availabilities matching with the provided characteristics.
func (c *Client) GetAvailabilities(ctx context.Context, params AvailabilityParams) (*AvailabilitiesResponse, error) { func (c *Client) GetAvailabilities(ctx context.Context, params AvailabilityParams, headers map[string]string) (*AvailabilitiesResponse, error) {
b, err := json.Marshal(params) b, err := json.Marshal(params)
if err != nil { if err != nil {
return nil, fmt.Errorf("fail to marshal availability params. Error: %w", err) return nil, fmt.Errorf("fail to marshal availability params. Error: %w", err)
@ -20,8 +20,8 @@ func (c *Client) GetAvailabilities(ctx context.Context, params AvailabilityParam
resp, err := c.get( resp, err := c.get(
ctx, ctx,
fmt.Sprintf("/inventory/api/v1/inventory-results?%s", queryParams.Encode()), fmt.Sprintf("/v1/inventory-results?%s", queryParams.Encode()),
nil, headers,
) )
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -5,6 +5,7 @@ import "time"
// modelEnum. // modelEnum.
type modelEnum string type modelEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
MODEL_3 modelEnum = "m3" MODEL_3 modelEnum = "m3"
MODEL_Y modelEnum = "my" MODEL_Y modelEnum = "my"
@ -15,6 +16,7 @@ const (
// conditionEnum. // conditionEnum.
type conditionEnum string type conditionEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
CONDITION_NEW conditionEnum = "new" CONDITION_NEW conditionEnum = "new"
CONDITION_USED conditionEnum = "used" CONDITION_USED conditionEnum = "used"
@ -23,6 +25,7 @@ const (
// arrangeByEnum allow to order availabilities by a specific element. // arrangeByEnum allow to order availabilities by a specific element.
type arrangeByEnum string type arrangeByEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
ARRANGE_BY_PRICE arrangeByEnum = "Price" ARRANGE_BY_PRICE arrangeByEnum = "Price"
ARRANGE_BY_ODOMETER arrangeByEnum = "Odometer" ARRANGE_BY_ODOMETER arrangeByEnum = "Odometer"
@ -33,6 +36,7 @@ const (
// orderByEnum. // orderByEnum.
type orderByEnum string type orderByEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
ORDER_BY_ASC orderByEnum = "asc" ORDER_BY_ASC orderByEnum = "asc"
ORDER_BY_DESC orderByEnum = "desc" ORDER_BY_DESC orderByEnum = "desc"
@ -45,6 +49,7 @@ const (
// autopilotEnum. // autopilotEnum.
type autopilotEnum string type autopilotEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
AUTOPILOT_AP autopilotEnum = "AUTOPILOT" AUTOPILOT_AP autopilotEnum = "AUTOPILOT"
AUTOPILOT_ENHANCED autopilotEnum = "ENHANCED_AUTOPILOT" AUTOPILOT_ENHANCED autopilotEnum = "ENHANCED_AUTOPILOT"
@ -55,6 +60,7 @@ const (
// cabinConfigEnum. // cabinConfigEnum.
type cabinConfigEnum string type cabinConfigEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
CABIN_CONFIG_FIVE cabinConfigEnum = "FIVE" CABIN_CONFIG_FIVE cabinConfigEnum = "FIVE"
CABIN_CONFIG_SIX cabinConfigEnum = "SIX" CABIN_CONFIG_SIX cabinConfigEnum = "SIX"
@ -64,6 +70,7 @@ const (
// interiorEnum. // interiorEnum.
type interiorEnum string type interiorEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
INTERIOR_CREAM interiorEnum = "CREAM" INTERIOR_CREAM interiorEnum = "CREAM"
INTERIOR_WHITE interiorEnum = "WHITE" INTERIOR_WHITE interiorEnum = "WHITE"
@ -73,6 +80,7 @@ const (
// paintEnum. // paintEnum.
type paintEnum string type paintEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
PAINT_RED paintEnum = "RED" PAINT_RED paintEnum = "RED"
PAINT_WHITE paintEnum = "WHITE" PAINT_WHITE paintEnum = "WHITE"
@ -85,6 +93,7 @@ const (
// steeringWheelEnum. // steeringWheelEnum.
type steeringWheelEnum string type steeringWheelEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
STEERING_WHEEL_YOKE steeringWheelEnum = "STEERING_YOKE" STEERING_WHEEL_YOKE steeringWheelEnum = "STEERING_YOKE"
STEERING_WHEEL_ROUND steeringWheelEnum = "STEERING_ROUND" STEERING_WHEEL_ROUND steeringWheelEnum = "STEERING_ROUND"
@ -93,6 +102,7 @@ const (
// trimEnum. // trimEnum.
type trimEnum string type trimEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
TRIM_MS_AWD trimEnum = "MSAWD" TRIM_MS_AWD trimEnum = "MSAWD"
TRIM_MS_PLAID trimEnum = "MSPLAID" TRIM_MS_PLAID trimEnum = "MSPLAID"
@ -109,6 +119,7 @@ const (
// wheelsEnum. // wheelsEnum.
type wheelsEnum string type wheelsEnum string
//nolint:exported // keeping the enum simple and readable.
const ( const (
WHEELS_18 wheelsEnum = "EIGHTEEN" WHEELS_18 wheelsEnum = "EIGHTEEN"
WHEELS_19 wheelsEnum = "NINETEEN" WHEELS_19 wheelsEnum = "NINETEEN"