1- import { constructStack } from "@aws-sdk/middleware-stack" ;
21import { HttpRequest } from "@aws-sdk/protocol-http" ;
32
4- import { bucketEndpointMiddleware , bucketEndpointMiddlewareOptions } from "./bucketEndpointMiddleware" ;
53import { resolveBucketEndpointConfig } from "./configurations" ;
64
5+ const mockBucketHostname = jest . fn ( ) ;
6+ jest . mock ( "./bucketHostname" , ( ) => ( {
7+ bucketHostname : mockBucketHostname ,
8+ } ) ) ;
9+ const mockBucketArn = "an ARN structure" ;
10+ const mockArnParse = jest . fn ( ) . mockReturnValue ( mockBucketArn ) ;
11+ const mockArnValidation = jest . fn ( ) ;
12+ jest . mock ( "@aws-sdk/util-arn-parser" , ( ) => ( {
13+ parse : mockArnParse ,
14+ validate : mockArnValidation ,
15+ } ) ) ;
16+
17+ import { bucketEndpointMiddleware } from "./bucketEndpointMiddleware" ;
18+
719describe ( "bucketEndpointMiddleware" , ( ) => {
820 const input = { Bucket : "bucket" } ;
921 const requestInput = {
@@ -14,140 +26,160 @@ describe("bucketEndpointMiddleware", () => {
1426 path : "/bucket" ,
1527 } ;
1628 const next = jest . fn ( ) ;
29+ const previouslyResolvedConfig = {
30+ region : jest . fn ( ) . mockResolvedValue ( "us-foo-1" ) ,
31+ regionInfoProvider : jest
32+ . fn ( )
33+ . mockResolvedValue ( { hostname : "foo.us-foo-2.amazonaws.com" , partition : "aws-foo" , signingRegion : "us-foo-1" } ) ,
34+ useArnRegion : jest . fn ( ) . mockResolvedValue ( false ) ,
35+ } ;
1736
18- beforeEach ( ( ) => {
19- next . mockClear ( ) ;
20- } ) ;
21-
22- it ( "should convert the request provided into one directed to a virtual hosted-style endpoint" , async ( ) => {
23- const request = new HttpRequest ( requestInput ) ;
24- const handler = bucketEndpointMiddleware ( resolveBucketEndpointConfig ( { } ) ) ( next , { } as any ) ;
25- await handler ( { input, request } ) ;
26-
27- const {
28- input : forwardedInput ,
29- request : { hostname, path } ,
30- } = next . mock . calls [ 0 ] [ 0 ] ;
31-
32- expect ( forwardedInput ) . toBe ( input ) ;
33- expect ( hostname ) . toBe ( "bucket.s3.us-west-2.amazonaws.com" ) ;
34- expect ( path ) . toBe ( "/" ) ;
35- } ) ;
36-
37- it ( "should not convert the request provided into one directed to a virtual hosted-style endpoint if so configured" , async ( ) => {
38- const request = new HttpRequest ( requestInput ) ;
39- const handler = bucketEndpointMiddleware (
40- resolveBucketEndpointConfig ( {
41- forcePathStyle : true ,
42- } )
43- ) ( next , { } as any ) ;
44- await handler ( { input, request } ) ;
45-
46- const {
47- input : forwardedInput ,
48- request : { hostname, path } ,
49- } = next . mock . calls [ 0 ] [ 0 ] ;
50-
51- expect ( forwardedInput ) . toBe ( input ) ;
52- expect ( hostname ) . toBe ( "s3.us-west-2.amazonaws.com" ) ;
53- expect ( path ) . toBe ( "/bucket" ) ;
37+ afterEach ( ( ) => {
38+ mockArnValidation . mockClear ( ) ;
39+ mockBucketHostname . mockClear ( ) ;
5440 } ) ;
5541
56- it ( "should use the bucket name as a virtual hosted-style endpoint if so configured" , async ( ) => {
57- const request = new HttpRequest ( requestInput ) ;
58- const handler = bucketEndpointMiddleware (
59- resolveBucketEndpointConfig ( {
42+ describe ( "with regular bucket name" , ( ) => {
43+ beforeEach ( ( ) => {
44+ mockBucketHostname . mockReturnValue ( {
6045 bucketEndpoint : true ,
61- } )
62- ) ( next , { } as any ) ;
63- await handler ( {
64- input : { Bucket : "files.domain.com" } ,
65- request : { ...request , path : "/files.domain.com/path/to/key.ext" } ,
46+ hostname : "bucket.s3.us-west-2.amazonaws.com" ,
47+ } ) ;
6648 } ) ;
6749
68- const {
69- request : { hostname, path } ,
70- } = next . mock . calls [ 0 ] [ 0 ] ;
71-
72- expect ( hostname ) . toBe ( "files.domain.com" ) ;
73- expect ( path ) . toBe ( "/path/to/key.ext" ) ;
74- } ) ;
75-
76- it ( "should use a transfer acceleration endpoint if so configured" , async ( ) => {
77- const request = new HttpRequest ( requestInput ) ;
78- const handler = bucketEndpointMiddleware (
79- resolveBucketEndpointConfig ( {
80- useAccelerateEndpoint : true ,
81- } )
82- ) ( next , { } as any ) ;
83- await handler ( { input, request } ) ;
84-
85- const {
86- input : forwardedInput ,
87- request : { hostname, path } ,
88- } = next . mock . calls [ 0 ] [ 0 ] ;
50+ it ( "should supply default parameters to bucket hostname constructor" , async ( ) => {
51+ const request = new HttpRequest ( requestInput ) ;
52+ mockArnValidation . mockReturnValue ( false ) ;
53+ const handler = bucketEndpointMiddleware (
54+ resolveBucketEndpointConfig ( {
55+ ...previouslyResolvedConfig ,
56+ } )
57+ ) ( next , { } as any ) ;
58+ await handler ( { input, request } ) ;
59+ expect ( mockBucketHostname ) . toBeCalled ( ) ;
60+ const param = mockBucketHostname . mock . calls [ 0 ] [ 0 ] ;
61+ expect ( param ) . toEqual ( {
62+ bucketName : input . Bucket ,
63+ baseHostname : requestInput . hostname ,
64+ accelerateEndpoint : false ,
65+ dualstackEndpoint : false ,
66+ pathStyleEndpoint : false ,
67+ tlsCompatible : true ,
68+ } ) ;
69+ } ) ;
8970
90- expect ( forwardedInput ) . toBe ( input ) ;
91- expect ( hostname ) . toBe ( "bucket.s3-accelerate.amazonaws.com" ) ;
92- expect ( path ) . toBe ( "/" ) ;
71+ it ( "should relay parameters to bucket hostname constructor" , async ( ) => {
72+ const request = new HttpRequest ( { ...requestInput , protocol : "http:" } ) ;
73+ mockArnValidation . mockReturnValue ( false ) ;
74+ const handler = bucketEndpointMiddleware (
75+ resolveBucketEndpointConfig ( {
76+ ...previouslyResolvedConfig ,
77+ useAccelerateEndpoint : true ,
78+ useDualstackEndpoint : true ,
79+ forcePathStyle : true ,
80+ } )
81+ ) ( next , { } as any ) ;
82+ await handler ( { input, request } ) ;
83+ expect ( mockBucketHostname ) . toBeCalled ( ) ;
84+ const param = mockBucketHostname . mock . calls [ 0 ] [ 0 ] ;
85+ expect ( param ) . toEqual ( {
86+ bucketName : input . Bucket ,
87+ baseHostname : requestInput . hostname ,
88+ accelerateEndpoint : true ,
89+ dualstackEndpoint : true ,
90+ pathStyleEndpoint : true ,
91+ tlsCompatible : false ,
92+ } ) ;
93+ } ) ;
9394 } ) ;
9495
95- it ( "should use a dualstack endpoint if so configured" , async ( ) => {
96- const request = new HttpRequest ( requestInput ) ;
97- const handler = bucketEndpointMiddleware (
98- resolveBucketEndpointConfig ( {
99- useDualstackEndpoint : true ,
100- } )
101- ) ( next , { } as any ) ;
102- await handler ( { input, request } ) ;
103-
104- const {
105- input : forwardedInput ,
106- request : { hostname, path } ,
107- } = next . mock . calls [ 0 ] [ 0 ] ;
108-
109- expect ( forwardedInput ) . toBe ( input ) ;
110- expect ( hostname ) . toBe ( "bucket.s3.dualstack.us-west-2.amazonaws.com" ) ;
111- expect ( path ) . toBe ( "/" ) ;
112- } ) ;
96+ describe ( "allows bucket name to be an ARN" , ( ) => {
97+ beforeEach ( ( ) => {
98+ mockArnValidation . mockReturnValue ( true ) ;
99+ mockBucketHostname . mockReturnValue ( {
100+ bucketEndpoint : true ,
101+ hostname : "myendpoint-123456789012.s3-accesspoint.us-west-2.amazonaws.com" ,
102+ } ) ;
103+ } ) ;
113104
114- it ( "should use an accelerate dualstack endpoint if configured" , async ( ) => {
115- const request = new HttpRequest ( requestInput ) ;
116- const handler = bucketEndpointMiddleware (
117- resolveBucketEndpointConfig ( {
118- useAccelerateEndpoint : true ,
119- useDualstackEndpoint : true ,
120- } )
121- ) ( next , { } as any ) ;
122- await handler ( { input, request } ) ;
105+ it ( "should relay parameters to bucket hostname constructor" , async ( ) => {
106+ const request = new HttpRequest ( requestInput ) ;
107+ const handler = bucketEndpointMiddleware (
108+ resolveBucketEndpointConfig ( {
109+ ...previouslyResolvedConfig ,
110+ } )
111+ ) ( next , { } as any ) ;
112+ await handler ( {
113+ input : { Bucket : "myendpoint-123456789012.s3-accesspoint.us-west-2.amazonaws.com" } ,
114+ request,
115+ } ) ;
116+ expect ( mockBucketHostname ) . toBeCalled ( ) ;
117+ const param = mockBucketHostname . mock . calls [ 0 ] [ 0 ] ;
118+ expect ( param ) . toEqual ( {
119+ bucketName : mockBucketArn ,
120+ baseHostname : requestInput . hostname ,
121+ accelerateEndpoint : false ,
122+ dualstackEndpoint : false ,
123+ pathStyleEndpoint : false ,
124+ tlsCompatible : true ,
125+ clientPartition : "aws-foo" ,
126+ clientSigningRegion : "us-foo-1" ,
127+ useArnRegion : false ,
128+ } ) ;
129+ expect ( previouslyResolvedConfig . region ) . toBeCalled ( ) ;
130+ expect ( previouslyResolvedConfig . regionInfoProvider ) . toBeCalled ( ) ;
131+ expect ( previouslyResolvedConfig . useArnRegion ) . toBeCalled ( ) ;
132+ } ) ;
123133
124- const {
125- request : { hostname, path } ,
126- } = next . mock . calls [ 0 ] [ 0 ] ;
134+ it ( "should get client partition and signing region with pseudo region" , async ( ) => {
135+ const request = new HttpRequest ( requestInput ) ;
136+ const handler = bucketEndpointMiddleware (
137+ resolveBucketEndpointConfig ( {
138+ ...previouslyResolvedConfig ,
139+ region : ( ) => Promise . resolve ( "fips-us-foo-1" ) ,
140+ } )
141+ ) ( next , { } as any ) ;
142+ await handler ( {
143+ input : { Bucket : "myendpoint-123456789012.s3-accesspoint.us-west-2.amazonaws.com" } ,
144+ request,
145+ } ) ;
146+ expect ( previouslyResolvedConfig . regionInfoProvider ) . toBeCalled ( ) ;
147+ expect ( previouslyResolvedConfig . regionInfoProvider . mock . calls [ 0 ] [ 0 ] ) . toBe ( "us-foo-1" ) ;
148+ } ) ;
127149
128- expect ( hostname ) . toBe ( "bucket.s3-accelerate.dualstack.amazonaws.com" ) ;
129- expect ( path ) . toBe ( "/" ) ;
130- } ) ;
150+ it ( "should supply bucketHostname in ARN object if bucket name string is a valid ARN" , async ( ) => {
151+ const request = new HttpRequest ( requestInput ) ;
152+ const handler = bucketEndpointMiddleware (
153+ resolveBucketEndpointConfig ( {
154+ ...previouslyResolvedConfig ,
155+ } )
156+ ) ( next , { } as any ) ;
157+ await handler ( {
158+ input : { Bucket : "myendpoint-123456789012.s3-accesspoint.us-west-2.amazonaws.com" } ,
159+ request,
160+ } ) ;
161+ expect ( mockBucketHostname ) . toBeCalled ( ) ;
162+ expect ( mockBucketHostname . mock . calls [ 0 ] [ 0 ] . bucketName ) . toBe ( mockBucketArn ) ;
163+ expect ( mockArnParse ) . toBeCalled ( ) ;
164+ expect ( mockArnValidation ) . toBeCalled ( ) ;
165+ } ) ;
131166
132- it ( "should be inserted before 'hostheaderMiddleware' if exists" , async ( ) => {
133- const stack = constructStack ( ) ;
134- const mockHostheaderMiddleware = ( next : any ) => ( args : any ) => {
135- args . request . arr . push ( "two" ) ;
136- return next ( args ) ;
137- } ;
138- const mockbucketEndpointMiddleware = ( next : any ) => ( args : any ) => {
139- args . request . arr . push ( "one" ) ;
140- return next ( args ) ;
141- } ;
142- stack . add ( mockHostheaderMiddleware , {
143- ...bucketEndpointMiddlewareOptions ,
144- name : bucketEndpointMiddlewareOptions . toMiddleware ,
167+ it ( "should set signing_region to middleware context if the request will use region from ARN" , async ( ) => {
168+ const request = new HttpRequest ( requestInput ) ;
169+ previouslyResolvedConfig . useArnRegion . mockReturnValue ( true ) ;
170+ const arnRegion = "us-west-2" ;
171+ mockArnParse . mockReturnValue ( { region : arnRegion } ) ;
172+ const handlerContext = { } as any ;
173+ const handler = bucketEndpointMiddleware (
174+ resolveBucketEndpointConfig ( {
175+ ...previouslyResolvedConfig ,
176+ } )
177+ ) ( next , handlerContext ) ;
178+ await handler ( {
179+ input : { Bucket : `myendpoint-123456789012.s3-accesspoint.${ arnRegion } .amazonaws.com` } ,
180+ request,
181+ } ) ;
182+ expect ( handlerContext ) . toMatchObject ( { signing_region : arnRegion } ) ;
145183 } ) ;
146- stack . addRelativeTo ( mockbucketEndpointMiddleware , bucketEndpointMiddlewareOptions ) ;
147- const handler = stack . resolve ( next , { } as any ) ;
148- expect . assertions ( 2 ) ;
149- await handler ( { request : { arr : [ ] } , input : { } } as any ) ;
150- expect ( next . mock . calls . length ) . toBe ( 1 ) ;
151- expect ( next . mock . calls [ 0 ] [ 0 ] . request . arr ) . toEqual ( [ "one" , "two" ] ) ;
152184 } ) ;
153185} ) ;
0 commit comments