1+ // Package httpclient provides an HTTP transport implementation for interacting with ROR APIs.
2+ // It offers various HTTP methods (GET, POST, PUT, DELETE, HEAD) with JSON serialization/deserialization,
3+ // authentication handling, retry mechanisms, and common HTTP client features.
4+ //
5+ // The client handles authentication through an injected AuthProvider interface, manages request
6+ // timeouts, and implements rate limiting through Retry-After response headers.
17package httpclient
28
39import (
@@ -15,72 +21,92 @@ import (
1521 "github.com/NorskHelsenett/ror/pkg/rlog"
1622)
1723
18- var (
19- DefaultTimeout = 60 * time .Second
20- )
24+ // DefaultTimeout defines the default HTTP request timeout duration
25+ var DefaultTimeout = 60 * time .Second
2126
27+ // HttpTransportClientParams encapsulates parameters for HTTP client requests
28+ // with a key-value structure to enable flexible configuration options.
2229type HttpTransportClientParams struct {
2330 Key HttpTransportClientOpts
2431 Value any
2532}
2633
34+ // HttpTransportClientOpts represents option types for HTTP client configuration.
2735type HttpTransportClientOpts string
2836
37+ // HttpTransportClientStatus tracks the connection state and version information
38+ // for the HTTP transport client, including retry timing information.
2939type HttpTransportClientStatus struct {
30- Established bool `json:"established"`
31- ApiVersion string `json:"api_version"`
32- LibVersion string `json:"lib_version"`
33- RetryAfter time.Time `json:"retry_after"`
34- }
35-
36- func NewHttpTransportClientStatus () * HttpTransportClientStatus {
37- return & HttpTransportClientStatus {
38- Established : false ,
39- ApiVersion : "unknown" ,
40- LibVersion : "unknown" ,
41- RetryAfter : time.Time {},
42- }
40+ Established bool `json:"established"` // Whether a connection has been established
41+ ApiVersion string `json:"api_version"` // Version of the remote API
42+ LibVersion string `json:"lib_version"` // Version of the client library
43+ RetryAfter time.Time `json:"retry_after"` // Time after which to retry if rate limited
4344}
4445
46+ // Available client configuration options
4547const (
46- HttpTransportClientOptsNoAuth HttpTransportClientOpts = "NOAUTH"
47- HttpTransportClientOptsHeaders HttpTransportClientOpts = "HEADERS"
48- HttpTransportClientOptsQuery HttpTransportClientOpts = "QUERY"
49- HttpTransportClientTimeout HttpTransportClientOpts = "TIMEOUT"
48+ HttpTransportClientOptsNoAuth HttpTransportClientOpts = "NOAUTH" // Skip authentication for this request
49+ HttpTransportClientOptsHeaders HttpTransportClientOpts = "HEADERS" // Add custom headers
50+ HttpTransportClientOptsQuery HttpTransportClientOpts = "QUERY" // Add query parameters
51+ HttpTransportClientTimeout HttpTransportClientOpts = "TIMEOUT" // Set request timeout
5052)
5153
52- // HttpTransportClientConfig is the configuration for the HTTP transport client
54+ // HttpTransportClientConfig defines the configuration for the HTTP transport client.
5355type HttpTransportClientConfig struct {
54- // BaseURL is the base URL for the API
55- // Example: https://api.example.com
56+ // BaseURL is the base URL for the API, e.g., "https://api.example.com"
5657 BaseURL string
57- // AuthProvider is the provider for the authentication
58+
59+ // AuthProvider handles request authentication
5860 AuthProvider HttpTransportAuthProvider
59- // Role is the role of the client
61+
62+ // Role identifies the client's purpose or role
6063 Role string
61- // Version is the version of the client
64+
65+ // Version identifies the client version
6266 Version rorversion.RorVersion
6367}
6468
69+ // HttpTransportAuthProvider is an interface that authentication providers must implement.
6570type HttpTransportAuthProvider interface {
71+ // AddAuthHeaders adds authentication headers to the request
6672 AddAuthHeaders (req * http.Request )
73+
74+ // GetApiSecret returns the API secret for authentication
6775 GetApiSecret () string
6876}
6977
78+ // HttpTransportClient implements an HTTP client with authentication, status tracking,
79+ // and standardized request/response handling.
7080type HttpTransportClient struct {
71- Client * http.Client
72- Config * HttpTransportClientConfig
73- Status * HttpTransportClientStatus
81+ Client * http.Client // Underlying HTTP client
82+ Config * HttpTransportClientConfig // Client configuration
83+ Status * HttpTransportClientStatus // Client connection status
7484}
7585
86+ // NewHttpTransportClientStatus creates a new client status object with default values.
87+ // The client starts as not established with unknown versions and no retry restrictions.
88+ func NewHttpTransportClientStatus () * HttpTransportClientStatus {
89+ return & HttpTransportClientStatus {
90+ Established : false ,
91+ ApiVersion : "" ,
92+ LibVersion : "" ,
93+ RetryAfter : time.Time {},
94+ }
95+ }
96+
97+ // GetRole returns the configured role of the client.
7698func (t * HttpTransportClientConfig ) GetRole () string {
7799 return t .Role
78100}
79101
102+ // GetJSON performs a GET request and unmarshals the JSON response into the out parameter.
103+ // This is a convenience wrapper around GetJSONWithContext using the background context.
80104func (t * HttpTransportClient ) GetJSON (path string , out any , params ... HttpTransportClientParams ) error {
81105 return t .GetJSONWithContext (context .TODO (), path , out , params ... )
82106}
83107
108+ // GetJSONWithContext performs a GET request with the provided context and unmarshals
109+ // the JSON response into the out parameter.
84110func (t * HttpTransportClient ) GetJSONWithContext (ctx context.Context , path string , out any , params ... HttpTransportClientParams ) error {
85111 if err := t .PreflightCheck (); err != nil {
86112 return err
@@ -111,10 +137,14 @@ func (t *HttpTransportClient) GetJSONWithContext(ctx context.Context, path strin
111137 return nil
112138}
113139
140+ // PostJSON performs a POST request with the provided input and unmarshals the JSON response into the out parameter.
141+ // This is a convenience wrapper around PostJSONWithContext using the background context.
114142func (t * HttpTransportClient ) PostJSON (path string , in any , out any , params ... HttpTransportClientParams ) error {
115143 return t .PostJSONWithContext (context .TODO (), path , in , out , params ... )
116144}
117145
146+ // PostJSONWithContext performs a POST request with the provided context and input,
147+ // then unmarshals the JSON response into the out parameter.
118148func (t * HttpTransportClient ) PostJSONWithContext (ctx context.Context , path string , in any , out any , params ... HttpTransportClientParams ) error {
119149 if err := t .PreflightCheck (); err != nil {
120150 return err
@@ -146,10 +176,14 @@ func (t *HttpTransportClient) PostJSONWithContext(ctx context.Context, path stri
146176 return nil
147177}
148178
179+ // PutJSON performs a PUT request with the provided input and unmarshals the JSON response into the out parameter.
180+ // This is a convenience wrapper around PutJSONWithContext using the background context.
149181func (t * HttpTransportClient ) PutJSON (path string , in any , out any , params ... HttpTransportClientParams ) error {
150182 return t .PutJSONWithContext (context .TODO (), path , in , out , params ... )
151183}
152184
185+ // PutJSONWithContext performs a PUT request with the provided context and input,
186+ // then unmarshals the JSON response into the out parameter.
153187func (t * HttpTransportClient ) PutJSONWithContext (ctx context.Context , path string , in any , out any , params ... HttpTransportClientParams ) error {
154188 if err := t .PreflightCheck (); err != nil {
155189 return err
@@ -180,10 +214,14 @@ func (t *HttpTransportClient) PutJSONWithContext(ctx context.Context, path strin
180214 return nil
181215}
182216
217+ // Delete performs a DELETE request and unmarshals the JSON response into the out parameter.
218+ // This is a convenience wrapper around DeleteWithContext using the background context.
183219func (t * HttpTransportClient ) Delete (path string , out any , params ... HttpTransportClientParams ) error {
184220 return t .DeleteWithContext (context .TODO (), path , out , params ... )
185221}
186222
223+ // DeleteWithContext performs a DELETE request with the provided context and
224+ // unmarshals the JSON response into the out parameter.
187225func (t * HttpTransportClient ) DeleteWithContext (ctx context.Context , path string , out any , params ... HttpTransportClientParams ) error {
188226 if err := t .PreflightCheck (); err != nil {
189227 return err
@@ -211,11 +249,14 @@ func (t *HttpTransportClient) DeleteWithContext(ctx context.Context, path string
211249}
212250
213251// Head makes a HEAD request with the given path and params.
214- // It returns only the header and status code from the result, as it expects no body in return.
252+ // It returns only the header and status code from the result, as HEAD requests have no response body.
253+ // This is a convenience wrapper around HeadWithContext using the background context.
215254func (t * HttpTransportClient ) Head (path string , params ... HttpTransportClientParams ) (http.Header , int , error ) {
216255 return t .HeadWithContext (context .TODO (), path , params ... )
217256}
218257
258+ // HeadWithContext performs a HEAD request with the provided context and returns
259+ // the response headers and status code.
219260func (t * HttpTransportClient ) HeadWithContext (ctx context.Context , path string , params ... HttpTransportClientParams ) (http.Header , int , error ) {
220261 if err := t .PreflightCheck (); err != nil {
221262 return nil , - 1 , err
@@ -242,7 +283,8 @@ func (t *HttpTransportClient) HeadWithContext(ctx context.Context, path string,
242283 return res .Header , res .StatusCode , nil
243284}
244285
245- // PreflightCheck by checking if retry-after is set client.Status.RetryAfter
286+ // PreflightCheck verifies if the client is ready to make a request by checking
287+ // if rate limiting is in effect via the RetryAfter timestamp.
246288func (t * HttpTransportClient ) PreflightCheck () error {
247289 // if t.Status == nil {
248290 // t.Status = NewHttpTransportClientStatus()
@@ -426,3 +468,24 @@ func (t *HttpTransportClientStatus) GetApiVersion() string {
426468func (t * HttpTransportClientStatus ) GetLibVersion () string {
427469 return t .LibVersion
428470}
471+
472+ // Example of creating and using the HTTP transport client:
473+ //
474+ // config := &httpclient.HttpTransportClientConfig{
475+ // BaseURL: "https://api.example.com",
476+ // AuthProvider: myAuthProvider,
477+ // Role: "api-client",
478+ // Version: myRorVersion,
479+ // }
480+ //
481+ // client := &httpclient.HttpTransportClient{
482+ // Client: &http.Client{Timeout: httpclient.DefaultTimeout},
483+ // Config: config,
484+ // Status: httpclient.NewHttpTransportClientStatus(),
485+ // }
486+ //
487+ // var response MyResponseType
488+ // err := client.GetJSON("/endpoint", &response, httpclient.HttpTransportClientParams{
489+ // Key: httpclient.HttpTransportClientOptsHeaders,
490+ // Value: map[string]string{"X-Custom-Header": "value"},
491+ //
0 commit comments