@@ -53,11 +53,10 @@ func NewClient(apiEndpoint string) *Client {
5353 }
5454 transport = otelhttp .NewTransport (transport )
5555
56- c := & Client {
56+ return & Client {
5757 apiEndpoint : apiEndpoint ,
5858 client : & http.Client {Transport : transport },
5959 }
60- return c
6160}
6261
6362func (c * Client ) Endpoint () string {
@@ -76,18 +75,17 @@ type PingResponse struct {
7675
7776// Ping is a minimal API used to ensure that the server is available.
7877func (c * Client ) Ping (ctx context.Context ) (* PingResponse , error ) {
79- req , err := http . NewRequestWithContext (ctx , http .MethodGet , backendURL ( "/ping" ) , http .NoBody )
78+ req , err := c . newRequest (ctx , http .MethodGet , "/ping" , http .NoBody )
8079 if err != nil {
8180 return nil , err
8281 }
83- req . Header . Set ( "User-Agent" , userAgent )
82+
8483 resp , err := c .client .Do (req )
8584 if err != nil {
8685 return nil , err
8786 }
88- defer func () {
89- _ = resp .Body .Close ()
90- }()
87+ defer resp .Body .Close ()
88+
9189 if resp .StatusCode != http .StatusOK {
9290 return nil , fmt .Errorf ("unexpected status code: %d" , resp .StatusCode )
9391 }
@@ -106,18 +104,17 @@ type FeatureFlagValue struct {
106104}
107105
108106func (c * Client ) FeatureFlags (ctx context.Context ) (FeatureFlagResponse , error ) {
109- req , err := http . NewRequestWithContext (ctx , http .MethodGet , backendURL ( "/features" ) , http .NoBody )
107+ req , err := c . newRequest (ctx , http .MethodGet , "/features" , http .NoBody )
110108 if err != nil {
111109 return nil , err
112110 }
113- req . Header . Set ( "User-Agent" , userAgent )
111+
114112 resp , err := c .client .Do (req )
115113 if err != nil {
116114 return nil , err
117115 }
118- defer func () {
119- _ = resp .Body .Close ()
120- }()
116+ defer resp .Body .Close ()
117+
121118 if resp .StatusCode != http .StatusOK {
122119 return nil , fmt .Errorf ("unexpected status code: %d" , resp .StatusCode )
123120 }
@@ -137,18 +134,16 @@ type GetFileSharesConfigResponse struct {
137134}
138135
139136func (c * Client ) GetFileSharesConfig (ctx context.Context ) (* GetFileSharesConfigResponse , error ) {
140- req , err := http . NewRequestWithContext (ctx , http .MethodGet , backendURL ( "/mutagen/file-shares/config" ) , http .NoBody )
137+ req , err := c . newRequest (ctx , http .MethodGet , "/mutagen/file-shares/config" , http .NoBody )
141138 if err != nil {
142139 return nil , err
143140 }
144- req . Header . Set ( "User-Agent" , userAgent )
141+
145142 resp , err := c .client .Do (req )
146143 if err != nil {
147144 return nil , err
148145 }
149- defer func () {
150- _ = resp .Body .Close ()
151- }()
146+ defer resp .Body .Close ()
152147
153148 if resp .StatusCode != http .StatusOK {
154149 return nil , newHTTPStatusCodeError (resp )
@@ -171,25 +166,28 @@ type CreateFileShareResponse struct {
171166}
172167
173168func (c * Client ) CreateFileShare (ctx context.Context , r CreateFileShareRequest ) (* CreateFileShareResponse , error ) {
174- rawBody , _ := json .Marshal (r )
175- req , err := http .NewRequestWithContext (ctx , http .MethodPost , backendURL ("/mutagen/file-shares" ), bytes .NewReader (rawBody ))
169+ rawBody , err := json .Marshal (r )
170+ if err != nil {
171+ return nil , fmt .Errorf ("failed to marshal request: %w" , err )
172+ }
173+
174+ req , err := c .newRequest (ctx , http .MethodPost , "/mutagen/file-shares" , bytes .NewReader (rawBody ))
176175 if err != nil {
177176 return nil , err
178177 }
179178 req .Header .Set ("Content-Type" , "application/json" )
180- req . Header . Set ( "User-Agent" , userAgent )
179+
181180 resp , err := c .client .Do (req )
182181 if err != nil {
183182 return nil , err
184183 }
185- defer func () {
186- _ = resp .Body .Close ()
187- }()
184+ defer resp .Body .Close ()
188185
189186 if resp .StatusCode != http .StatusOK {
190187 errBody , _ := io .ReadAll (resp .Body )
191188 return nil , fmt .Errorf ("unexpected status code %d: %s" , resp .StatusCode , string (errBody ))
192189 }
190+
193191 var ret CreateFileShareResponse
194192 if err := json .NewDecoder (resp .Body ).Decode (& ret ); err != nil {
195193 return nil , err
@@ -216,18 +214,16 @@ type FileShareSession struct {
216214}
217215
218216func (c * Client ) ListFileShares (ctx context.Context ) ([]FileShareSession , error ) {
219- req , err := http . NewRequestWithContext (ctx , http .MethodGet , backendURL ( "/mutagen/file-shares" ) , http .NoBody )
217+ req , err := c . newRequest (ctx , http .MethodGet , "/mutagen/file-shares" , http .NoBody )
220218 if err != nil {
221219 return nil , err
222220 }
223- req . Header . Set ( "User-Agent" , userAgent )
221+
224222 resp , err := c .client .Do (req )
225223 if err != nil {
226224 return nil , err
227225 }
228- defer func () {
229- _ = resp .Body .Close ()
230- }()
226+ defer resp .Body .Close ()
231227
232228 if resp .StatusCode != http .StatusOK {
233229 return nil , newHTTPStatusCodeError (resp )
@@ -241,18 +237,17 @@ func (c *Client) ListFileShares(ctx context.Context) ([]FileShareSession, error)
241237}
242238
243239func (c * Client ) DeleteFileShare (ctx context.Context , id string ) error {
244- req , err := http . NewRequestWithContext (ctx , http .MethodDelete , backendURL ( "/mutagen/file-shares/" + id ) , http .NoBody )
240+ req , err := c . newRequest (ctx , http .MethodDelete , "/mutagen/file-shares/" + id , http .NoBody )
245241 if err != nil {
246242 return err
247243 }
248- req . Header . Set ( "User-Agent" , userAgent )
244+
249245 resp , err := c .client .Do (req )
250246 if err != nil {
251247 return err
252248 }
253- defer func () {
254- _ = resp .Body .Close ()
255- }()
249+ defer resp .Body .Close ()
250+
256251 if resp .StatusCode < 200 || resp .StatusCode >= 300 {
257252 return newHTTPStatusCodeError (resp )
258253 }
@@ -274,30 +269,25 @@ func newHTTPStatusCodeError(resp *http.Response) error {
274269}
275270
276271func (c * Client ) StreamFileShares (ctx context.Context ) (<- chan EventMessage [[]FileShareSession ], error ) {
277- req , err := http . NewRequestWithContext (ctx , http .MethodGet , backendURL ( "/mutagen/file-shares/stream" ) , http .NoBody )
272+ req , err := c . newRequest (ctx , http .MethodGet , "/mutagen/file-shares/stream" , http .NoBody )
278273 if err != nil {
279274 return nil , err
280275 }
281- req . Header . Set ( "User-Agent" , userAgent )
276+
282277 resp , err := c .client .Do (req )
283278 if err != nil {
284279 return nil , err
285280 }
286281
287282 if resp .StatusCode < 200 || resp .StatusCode >= 300 {
288- defer func () {
289- _ = resp .Body .Close ()
290- }()
283+ _ = resp .Body .Close ()
291284 return nil , newHTTPStatusCodeError (resp )
292285 }
293286
294287 events := make (chan EventMessage [[]FileShareSession ])
295288 go func (ctx context.Context ) {
296289 defer func () {
297290 _ = resp .Body .Close ()
298- for range events {
299- // drain the channel
300- }
301291 close (events )
302292 }()
303293 if err := readEvents (ctx , resp .Body , events ); err != nil {
@@ -334,6 +324,15 @@ func readEvents[T any](ctx context.Context, r io.Reader, events chan<- EventMess
334324 }
335325}
336326
327+ func (c * Client ) newRequest (ctx context.Context , method , path string , body io.Reader ) (* http.Request , error ) {
328+ req , err := http .NewRequestWithContext (ctx , method , backendURL (path ), body )
329+ if err != nil {
330+ return nil , err
331+ }
332+ req .Header .Set ("User-Agent" , userAgent )
333+ return req , nil
334+ }
335+
337336// backendURL generates a URL for the given API path.
338337//
339338// NOTE: Custom transport handles communication. The host is to create a valid
0 commit comments