Skip to content

Commit f262272

Browse files
authored
IAM: Reduce code duplication in HTTP client (#3079)
1 parent 2f6f04d commit f262272

File tree

2 files changed

+49
-157
lines changed

2 files changed

+49
-157
lines changed

auth/client/iam/client.go

Lines changed: 18 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,11 @@ func (hb HTTPClient) OAuthAuthorizationServerMetadata(ctx context.Context, webDI
5353
if err != nil {
5454
return nil, err
5555
}
56-
57-
request, err := http.NewRequestWithContext(ctx, http.MethodGet, metadataURL.String(), nil)
58-
if err != nil {
59-
return nil, err
60-
}
61-
response, err := hb.httpClient.Do(request.WithContext(ctx))
62-
if err != nil {
63-
return nil, err
64-
}
65-
66-
if err = core.TestResponseCode(http.StatusOK, response); err != nil {
67-
return nil, err
68-
}
69-
7056
var metadata oauth.AuthorizationServerMetadata
71-
var data []byte
72-
73-
if data, err = core.LimitedReadAll(response.Body); err != nil {
74-
return nil, fmt.Errorf("unable to read response: %w", err)
75-
}
76-
if err = json.Unmarshal(data, &metadata); err != nil {
77-
return nil, fmt.Errorf("unable to unmarshal response: %w, %s", err, string(data))
57+
if err = hb.doGet(ctx, metadataURL.String(), &metadata); err != nil {
58+
return nil, err
7859
}
79-
80-
return &metadata, nil
60+
return &metadata, err
8161
}
8262

8363
// ClientMetadata retrieves the client metadata from the client metadata endpoint given in the authorization request.
@@ -123,7 +103,7 @@ func (hb HTTPClient) RequestObject(ctx context.Context, requestURI string) (stri
123103
return "", httpErr
124104
}
125105

126-
data, err := io.ReadAll(response.Body)
106+
data, err := core.LimitedReadAll(response.Body)
127107
if err != nil {
128108
return "", fmt.Errorf("unable to read response: %w", err)
129109
}
@@ -206,68 +186,29 @@ func (hb HTTPClient) OpenIdConfiguration(ctx context.Context, serverURL string)
206186
if err != nil {
207187
return nil, err
208188
}
209-
210-
request, err := http.NewRequestWithContext(ctx, http.MethodGet, metadataURL.String(), nil)
211-
if err != nil {
212-
return nil, err
213-
}
214-
response, err := hb.httpClient.Do(request.WithContext(ctx))
189+
var metadata oauth.OpenIDConfigurationMetadata
190+
err = hb.doGet(ctx, metadataURL.String(), &metadata)
215191
if err != nil {
216-
return nil, fmt.Errorf("failed to call endpoint: %w", err)
217-
}
218-
219-
if err = core.TestResponseCode(http.StatusOK, response); err != nil {
220192
return nil, err
221193
}
222-
223-
var metadata oauth.OpenIDConfigurationMetadata
224-
var data []byte
225-
226-
if data, err = core.LimitedReadAll(response.Body); err != nil {
227-
return nil, fmt.Errorf("unable to read response: %w", err)
228-
}
229-
if err = json.Unmarshal(data, &metadata); err != nil {
230-
return nil, fmt.Errorf("unable to unmarshal response: %w, %s", err, string(data))
231-
}
232-
233-
return &metadata, nil
194+
return &metadata, err
234195
}
235196

236197
func (hb HTTPClient) OpenIdCredentialIssuerMetadata(ctx context.Context, webDID did.DID) (*oauth.OpenIDCredentialIssuerMetadata, error) {
237198
serverURL, err := didweb.DIDToURL(webDID)
238199
if err != nil {
239200
return nil, err
240201
}
241-
242202
metadataURL, err := oauth.IssuerIdToWellKnown(serverURL.String(), oauth.OpenIdCredIssuerWellKnown, hb.strictMode)
243203
if err != nil {
244204
return nil, err
245205
}
246-
247-
request, err := http.NewRequestWithContext(ctx, http.MethodGet, metadataURL.String(), nil)
206+
var metadata oauth.OpenIDCredentialIssuerMetadata
207+
err = hb.doGet(ctx, metadataURL.String(), &metadata)
248208
if err != nil {
249209
return nil, err
250210
}
251-
response, err := hb.httpClient.Do(request.WithContext(ctx))
252-
if err != nil {
253-
return nil, fmt.Errorf("failed to call endpoint: %w", err)
254-
}
255-
256-
if err = core.TestResponseCode(http.StatusOK, response); err != nil {
257-
return nil, err
258-
}
259-
260-
var metadata oauth.OpenIDCredentialIssuerMetadata
261-
var data []byte
262-
263-
if data, err = core.LimitedReadAll(response.Body); err != nil {
264-
return nil, fmt.Errorf("unable to read response: %w", err)
265-
}
266-
if err = json.Unmarshal(data, &metadata); err != nil {
267-
return nil, fmt.Errorf("unable to unmarshal response: %w, %s", err, string(data))
268-
}
269-
270-
return &metadata, nil
211+
return &metadata, err
271212
}
272213

273214
func (hb HTTPClient) AccessTokenOid4vci(ctx context.Context, presentationDefinitionURL url.URL, data url.Values) (*oauth.Oid4vciTokenResponse, error) {
@@ -390,6 +331,14 @@ func (hb HTTPClient) postFormExpectRedirect(ctx context.Context, form url.Values
390331
return redirect.RedirectURI, nil
391332
}
392333

334+
func (hb HTTPClient) doGet(ctx context.Context, requestURL string, target interface{}) error {
335+
request, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
336+
if err != nil {
337+
return err
338+
}
339+
return hb.doRequest(ctx, request, target)
340+
}
341+
393342
func (hb HTTPClient) doRequest(ctx context.Context, request *http.Request, target interface{}) error {
394343
response, err := hb.httpClient.Do(request.WithContext(ctx))
395344
if err != nil {

auth/client/iam/client_test.go

Lines changed: 31 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -71,35 +71,6 @@ func TestHTTPClient_OAuthAuthorizationServerMetadata(t *testing.T) {
7171
assert.Equal(t, "GET", handler.Request.Method)
7272
assert.Equal(t, "/.well-known/oauth-authorization-server/iam/123", handler.Request.URL.Path)
7373
})
74-
t.Run("error - non 200 return value", func(t *testing.T) {
75-
handler := http2.Handler{StatusCode: http.StatusBadRequest}
76-
tlsServer, client := testServerAndClient(t, &handler)
77-
testDID := didweb.ServerURLToDIDWeb(t, tlsServer.URL)
78-
79-
metadata, err := client.OAuthAuthorizationServerMetadata(ctx, testDID)
80-
81-
assert.Error(t, err)
82-
assert.Nil(t, metadata)
83-
})
84-
t.Run("error - bad contents", func(t *testing.T) {
85-
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: "not json"}
86-
tlsServer, client := testServerAndClient(t, &handler)
87-
testDID := didweb.ServerURLToDIDWeb(t, tlsServer.URL)
88-
89-
metadata, err := client.OAuthAuthorizationServerMetadata(ctx, testDID)
90-
91-
assert.Error(t, err)
92-
assert.Nil(t, metadata)
93-
})
94-
t.Run("error - server not responding", func(t *testing.T) {
95-
_, client := testServerAndClient(t, nil)
96-
testDID := didweb.ServerURLToDIDWeb(t, "https://localhost:1234")
97-
98-
metadata, err := client.OAuthAuthorizationServerMetadata(ctx, testDID)
99-
100-
assert.Error(t, err)
101-
assert.Nil(t, metadata)
102-
})
10374
}
10475

10576
func TestHTTPClient_PresentationDefinition(t *testing.T) {
@@ -120,26 +91,6 @@ func TestHTTPClient_PresentationDefinition(t *testing.T) {
12091
assert.Equal(t, definition, *response)
12192
require.NotNil(t, handler.Request)
12293
})
123-
t.Run("error - not found", func(t *testing.T) {
124-
handler := http2.Handler{StatusCode: http.StatusNotFound}
125-
tlsServer, client := testServerAndClient(t, &handler)
126-
pdUrl := test.MustParseURL(tlsServer.URL)
127-
128-
_, err := client.PresentationDefinition(ctx, *pdUrl)
129-
130-
require.Error(t, err)
131-
assert.EqualError(t, err, "server returned HTTP 404 (expected: 200)")
132-
})
133-
t.Run("error - invalid response", func(t *testing.T) {
134-
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: "}"}
135-
tlsServer, client := testServerAndClient(t, &handler)
136-
pdUrl := test.MustParseURL(tlsServer.URL)
137-
138-
_, err := client.PresentationDefinition(ctx, *pdUrl)
139-
140-
require.Error(t, err)
141-
assert.EqualError(t, err, "unable to unmarshal response: invalid character '}' looking for beginning of value")
142-
})
14394
}
14495

14596
func TestHTTPClient_AccessToken(t *testing.T) {
@@ -224,23 +175,12 @@ func TestHTTPClient_ClientMetadata(t *testing.T) {
224175
assert.Equal(t, metadata, *response)
225176
require.NotNil(t, handler.Request)
226177
})
227-
228-
t.Run("error - incorrect url", func(t *testing.T) {
229-
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: metadata}
230-
_, client := testServerAndClient(t, &handler)
231-
232-
_, err := client.ClientMetadata(ctx, ":")
233-
234-
require.Error(t, err)
235-
assert.EqualError(t, err, "parse \":\": missing protocol scheme")
236-
})
237178
}
238179

239180
func TestHTTPClient_PostError(t *testing.T) {
240181
redirectReturn := oauth.Redirect{
241182
RedirectURI: "http://test.test",
242183
}
243-
//bytes, _ := json.Marshal(redirectReturn)
244184
t.Run("ok", func(t *testing.T) {
245185
ctx := context.Background()
246186
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: redirectReturn}
@@ -280,41 +220,16 @@ func TestHTTPClient_postFormExpectRedirect(t *testing.T) {
280220
data := url.Values{}
281221
data.Set("test", "test")
282222

283-
t.Run("error - unknown host", func(t *testing.T) {
223+
t.Run("ok", func(t *testing.T) {
284224
ctx := context.Background()
285225
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: redirectReturn}
286-
_, client := testServerAndClient(t, &handler)
287-
tlsServerURL := test.MustParseURL("http://localhost")
288-
289-
redirectURI, err := client.postFormExpectRedirect(ctx, data, *tlsServerURL)
290-
291-
require.Error(t, err)
292-
assert.ErrorContains(t, err, "connection refused")
293-
assert.Empty(t, redirectURI)
294-
})
295-
t.Run("error - invalid response", func(t *testing.T) {
296-
ctx := context.Background()
297-
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: "}"}
298226
tlsServer, client := testServerAndClient(t, &handler)
299227
tlsServerURL := test.MustParseURL(tlsServer.URL)
300228

301229
redirectURI, err := client.postFormExpectRedirect(ctx, data, *tlsServerURL)
302230

303-
require.Error(t, err)
304-
assert.EqualError(t, err, "unable to unmarshal response: invalid character '}' looking for beginning of value")
305-
assert.Empty(t, redirectURI)
306-
})
307-
t.Run("error - server error", func(t *testing.T) {
308-
ctx := context.Background()
309-
handler := http2.Handler{StatusCode: http.StatusBadGateway, ResponseData: "offline"}
310-
tlsServer, client := testServerAndClient(t, &handler)
311-
tlsServerURL := test.MustParseURL(tlsServer.URL)
312-
313-
redirectURI, err := client.postFormExpectRedirect(ctx, data, *tlsServerURL)
314-
315-
require.Error(t, err)
316-
assert.EqualError(t, err, "server returned HTTP 502 (expected: 200)")
317-
assert.Empty(t, redirectURI)
231+
require.NoError(t, err)
232+
assert.Equal(t, redirectReturn.RedirectURI, redirectURI)
318233
})
319234
}
320235

@@ -359,3 +274,31 @@ func testServerAndClient(t *testing.T, handler http.Handler) (*httptest.Server,
359274
httpClient: tlsServer.Client(),
360275
}
361276
}
277+
278+
func TestHTTPClient_doGet(t *testing.T) {
279+
t.Run("error - non 200 return value", func(t *testing.T) {
280+
handler := http2.Handler{StatusCode: http.StatusBadRequest}
281+
tlsServer, client := testServerAndClient(t, &handler)
282+
283+
err := client.doGet(context.Background(), tlsServer.URL, nil)
284+
285+
assert.Error(t, err)
286+
})
287+
t.Run("error - bad contents", func(t *testing.T) {
288+
handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: "not json"}
289+
tlsServer, client := testServerAndClient(t, &handler)
290+
291+
var target interface{}
292+
err := client.doGet(context.Background(), tlsServer.URL, &target)
293+
294+
assert.Error(t, err)
295+
})
296+
t.Run("error - server not responding", func(t *testing.T) {
297+
_, client := testServerAndClient(t, nil)
298+
299+
var target interface{}
300+
err := client.doGet(context.Background(), "https://localhost:9999", &target)
301+
302+
assert.Error(t, err)
303+
})
304+
}

0 commit comments

Comments
 (0)