Skip to content

Commit 3196e42

Browse files
authored
Fix sync response link populating (#32)
1 parent b753f0d commit 3196e42

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

nexus/client.go

+20-12
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,25 @@ func (c *HTTPClient) StartOperation(
219219
if err != nil {
220220
return nil, err
221221
}
222+
223+
links, err := getLinksFromHeader(response.Header)
224+
if err != nil {
225+
// Have to read body here to check if it is a Failure.
226+
body, err := readAndReplaceBody(response)
227+
if err != nil {
228+
return nil, err
229+
}
230+
return nil, fmt.Errorf(
231+
"%w: %w",
232+
newUnexpectedResponseError(
233+
fmt.Sprintf("invalid links header: %q", response.Header.Values(headerLink)),
234+
response,
235+
body,
236+
),
237+
err,
238+
)
239+
}
240+
222241
// Do not close response body here to allow successful result to read it.
223242
if response.StatusCode == http.StatusOK {
224243
return &ClientStartOperationResult[*LazyValue]{
@@ -229,6 +248,7 @@ func (c *HTTPClient) StartOperation(
229248
prefixStrippedHTTPHeaderToNexusHeader(response.Header, "content-"),
230249
},
231250
},
251+
Links: links,
232252
}, nil
233253
}
234254

@@ -247,18 +267,6 @@ func (c *HTTPClient) StartOperation(
247267
if info.State != OperationStateRunning {
248268
return nil, newUnexpectedResponseError(fmt.Sprintf("invalid operation state in response info: %q", info.State), response, body)
249269
}
250-
links, err := getLinksFromHeader(response.Header)
251-
if err != nil {
252-
return nil, fmt.Errorf(
253-
"%w: %w",
254-
newUnexpectedResponseError(
255-
fmt.Sprintf("invalid links header: %q", response.Header.Values(headerLink)),
256-
response,
257-
body,
258-
),
259-
err,
260-
)
261-
}
262270
return &ClientStartOperationResult[*LazyValue]{
263271
Pending: &OperationHandle[*LazyValue]{
264272
Operation: operation,

nexus/operation.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func (h *syncOperation[I, O]) Start(ctx context.Context, input I, options StartO
125125
if err != nil {
126126
return nil, err
127127
}
128-
return &HandlerStartOperationResultSync[O]{Value: o, Links: options.Links}, err
128+
return &HandlerStartOperationResultSync[O]{Value: o}, err
129129
}
130130

131131
// A Service is a container for a group of operations.
@@ -344,7 +344,10 @@ func StartOperation[I, O any](ctx context.Context, client *HTTPClient, operation
344344
if err := result.Successful.Consume(&o); err != nil {
345345
return nil, err
346346
}
347-
return &ClientStartOperationResult[O]{Successful: o}, nil
347+
return &ClientStartOperationResult[O]{
348+
Successful: o,
349+
Links: result.Links,
350+
}, nil
348351
}
349352
handle := OperationHandle[O]{client: client, Operation: operation.Name(), ID: result.Pending.ID}
350353
return &ClientStartOperationResult[O]{

nexus/start_test.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"fmt"
77
"io"
8+
"net/url"
89
"testing"
910
"time"
1011

@@ -47,7 +48,7 @@ func (h *successHandler) StartOperation(ctx context.Context, service, operation
4748
return nil, HandlerErrorf(HandlerErrorTypeBadRequest, "invalid 'User-Agent' header: %q", options.Header.Get("User-Agent"))
4849
}
4950

50-
return &HandlerStartOperationResultSync[any]{Value: body, Links: options.Links}, nil
51+
return &HandlerStartOperationResultSync[any]{Value: body}, nil
5152
}
5253

5354
func TestSuccess(t *testing.T) {
@@ -110,6 +111,7 @@ func TestClientRequestID(t *testing.T) {
110111
t.Run(c.name, func(t *testing.T) {
111112
result, err := client.StartOperation(ctx, "foo", nil, c.request)
112113
require.NoError(t, err)
114+
require.Equal(t, c.request.Links, result.Links)
113115
response := result.Successful
114116
require.NotNil(t, response)
115117
var responseBody []byte
@@ -165,7 +167,7 @@ func (h *echoHandler) StartOperation(ctx context.Context, service, operation str
165167
Data: data,
166168
}
167169
}
168-
return &HandlerStartOperationResultSync[any]{Value: output}, nil
170+
return &HandlerStartOperationResultSync[any]{Value: output, Links: options.Links}, nil
169171
}
170172

171173
func TestReaderIO(t *testing.T) {
@@ -182,6 +184,7 @@ func TestReaderIO(t *testing.T) {
182184
name string
183185
input any
184186
header Header
187+
links []Link
185188
}{
186189
{
187190
name: "content",
@@ -192,14 +195,24 @@ func TestReaderIO(t *testing.T) {
192195
name: "reader",
193196
input: reader,
194197
header: Header{"input-type": "reader"},
198+
links: []Link{{
199+
URL: &url.URL{
200+
Scheme: "https",
201+
Host: "example.com",
202+
Path: "/path/to/something",
203+
RawQuery: "param=value",
204+
},
205+
Type: "url",
206+
}},
195207
},
196208
}
197209

198210
for _, tc := range testCases {
199211
tc := tc
200212
t.Run(tc.name, func(t *testing.T) {
201-
result, err := client.StartOperation(ctx, "foo", tc.input, StartOperationOptions{Header: tc.header})
213+
result, err := client.StartOperation(ctx, "foo", tc.input, StartOperationOptions{Header: tc.header, Links: tc.links})
202214
require.NoError(t, err)
215+
require.Equal(t, tc.links, result.Links)
203216
response := result.Successful
204217
require.NotNil(t, response)
205218
var operationResult string

0 commit comments

Comments
 (0)