Skip to content

Commit

Permalink
fix(signature-v4): add hoistable headers config (#1421)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe authored Sep 30, 2024
1 parent 41a96d4 commit a4c1285
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changeset/happy-emus-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@smithy/signature-v4": minor
"@smithy/types": minor
---

configurable hoisted headers
3 changes: 2 additions & 1 deletion packages/signature-v4/src/SignatureV4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export class SignatureV4 implements RequestPresigner, RequestSigner, StringSigne
unsignableHeaders,
unhoistableHeaders,
signableHeaders,
hoistableHeaders,
signingRegion,
signingService,
} = options;
Expand All @@ -146,7 +147,7 @@ export class SignatureV4 implements RequestPresigner, RequestSigner, StringSigne
}

const scope = createScope(shortDate, region, signingService ?? this.service);
const request = moveHeadersToQuery(prepareRequest(originalRequest), { unhoistableHeaders });
const request = moveHeadersToQuery(prepareRequest(originalRequest), { unhoistableHeaders, hoistableHeaders });

if (credentials.sessionToken) {
request.query[TOKEN_QUERY_PARAM] = credentials.sessionToken;
Expand Down
32 changes: 32 additions & 0 deletions packages/signature-v4/src/moveHeadersToQuery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,36 @@ describe("moveHeadersToQuery", () => {
SNAP: "crackle, pop",
});
});

it("should obey hoistableHeaders configuration over unhoistableHeaders", () => {
const req = moveHeadersToQuery(
new HttpRequest({
...minimalRequest,
headers: {
Host: "www.example.com",
"X-Amz-Website-Redirect-Location": "/index.html",
Foo: "bar",
fizz: "buzz",
SNAP: "crackle, pop",
"X-Amz-Storage-Class": "STANDARD_IA",
},
}),
{
hoistableHeaders: new Set(["x-amz-website-redirect-location", "snap"]),
unhoistableHeaders: new Set(["x-amz-website-redirect-location"]),
}
);

expect(req.query).toEqual({
SNAP: "crackle, pop",
"X-Amz-Storage-Class": "STANDARD_IA",
"X-Amz-Website-Redirect-Location": "/index.html",
});

expect(req.headers).toEqual({
Host: "www.example.com",
Foo: "bar",
fizz: "buzz",
});
});
});
7 changes: 5 additions & 2 deletions packages/signature-v4/src/moveHeadersToQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import type { HttpRequest as IHttpRequest, QueryParameterBag } from "@smithy/typ
*/
export const moveHeadersToQuery = (
request: IHttpRequest,
options: { unhoistableHeaders?: Set<string> } = {}
options: { unhoistableHeaders?: Set<string>; hoistableHeaders?: Set<string> } = {}
): IHttpRequest & { query: QueryParameterBag } => {
const { headers, query = {} as QueryParameterBag } = HttpRequest.clone(request);
for (const name of Object.keys(headers)) {
const lname = name.toLowerCase();
if (lname.slice(0, 6) === "x-amz-" && !options.unhoistableHeaders?.has(lname)) {
if (
(lname.slice(0, 6) === "x-amz-" && !options.unhoistableHeaders?.has(lname)) ||
options.hoistableHeaders?.has(lname)
) {
query[name] = headers[name];
delete headers[name];
}
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ export interface RequestPresigningArguments extends RequestSigningArguments {
* lower case and then checked for existence in the unhoistableHeaders set.
*/
unhoistableHeaders?: Set<string>;

/**
* This overrides any headers with the same name(s) set by unhoistableHeaders.
* These headers will be hoisted into the query string and signed.
*/
hoistableHeaders?: Set<string>;
}

/**
Expand Down

0 comments on commit a4c1285

Please sign in to comment.