1
1
import { Context } from 'hono' ;
2
- import { Options } from '../../types/requestBody' ;
2
+ import { Options , Params } from '../../types/requestBody' ;
3
3
import { endpointStrings , ProviderAPIConfig } from '../types' ;
4
4
import { bedrockInvokeModels } from './constants' ;
5
5
import {
6
+ getAwsEndpointDomain ,
6
7
generateAWSHeaders ,
7
- getAssumedRoleCredentials ,
8
8
getFoundationModelFromInferenceProfile ,
9
9
providerAssumedRoleCredentials ,
10
10
} from './utils' ;
@@ -18,6 +18,7 @@ interface BedrockAPIConfigInterface extends Omit<ProviderAPIConfig, 'headers'> {
18
18
transformedRequestBody : Record < string , any > | string ;
19
19
transformedRequestUrl : string ;
20
20
gatewayRequestBody ?: Params ;
21
+ headers ?: Record < string , string > ;
21
22
} ) => Promise < Record < string , any > > | Record < string , any > ;
22
23
}
23
24
@@ -66,7 +67,14 @@ const ENDPOINTS_TO_ROUTE_TO_S3 = [
66
67
'initiateMultipartUpload' ,
67
68
] ;
68
69
69
- const getMethod = ( fn : endpointStrings , transformedRequestUrl : string ) => {
70
+ const getMethod = (
71
+ fn : endpointStrings ,
72
+ transformedRequestUrl : string ,
73
+ c : Context
74
+ ) => {
75
+ if ( fn === 'proxy' ) {
76
+ return c . req . method ;
77
+ }
70
78
if ( fn === 'uploadFile' ) {
71
79
const url = new URL ( transformedRequestUrl ) ;
72
80
return url . searchParams . get ( 'partNumber' ) ? 'PUT' : 'POST' ;
@@ -121,36 +129,47 @@ const BedrockAPIConfig: BedrockAPIConfigInterface = {
121
129
gatewayRequestURL . split ( '/v1/files/' ) [ 1 ]
122
130
) ;
123
131
const bucketName = s3URL . replace ( 's3://' , '' ) . split ( '/' ) [ 0 ] ;
124
- return `https://${ bucketName } .s3.${ providerOptions . awsRegion || 'us-east-1' } .amazonaws.com ` ;
132
+ return `https://${ bucketName } .s3.${ providerOptions . awsRegion || 'us-east-1' } .${ getAwsEndpointDomain ( c ) } ` ;
125
133
}
126
134
if ( fn === 'retrieveFileContent' ) {
127
135
const s3URL = decodeURIComponent (
128
136
gatewayRequestURL . split ( '/v1/files/' ) [ 1 ]
129
137
) ;
130
138
const bucketName = s3URL . replace ( 's3://' , '' ) . split ( '/' ) [ 0 ] ;
131
- return `https://${ bucketName } .s3.${ providerOptions . awsRegion || 'us-east-1' } .amazonaws.com ` ;
139
+ return `https://${ bucketName } .s3.${ providerOptions . awsRegion || 'us-east-1' } .${ getAwsEndpointDomain ( c ) } ` ;
132
140
}
133
141
if ( fn === 'uploadFile' )
134
- return `https://${ providerOptions . awsS3Bucket } .s3.${ providerOptions . awsRegion || 'us-east-1' } .amazonaws.com ` ;
142
+ return `https://${ providerOptions . awsS3Bucket } .s3.${ providerOptions . awsRegion || 'us-east-1' } .${ getAwsEndpointDomain ( c ) } ` ;
135
143
const isAWSControlPlaneEndpoint =
136
144
fn && AWS_CONTROL_PLANE_ENDPOINTS . includes ( fn ) ;
137
- return `https://${ isAWSControlPlaneEndpoint ? 'bedrock' : 'bedrock-runtime' } .${ providerOptions . awsRegion || 'us-east-1' } .amazonaws.com ` ;
145
+ return `https://${ isAWSControlPlaneEndpoint ? 'bedrock' : 'bedrock-runtime' } .${ providerOptions . awsRegion || 'us-east-1' } .${ getAwsEndpointDomain ( c ) } ` ;
138
146
} ,
139
147
headers : async ( {
140
148
c,
141
149
fn,
142
150
providerOptions,
143
151
transformedRequestBody,
144
152
transformedRequestUrl,
153
+ gatewayRequestBody, // for proxy use the passed body blindly
154
+ headers : requestHeaders ,
145
155
} ) => {
146
- const method = getMethod ( fn as endpointStrings , transformedRequestUrl ) ;
147
- const service = getService ( fn as endpointStrings ) ;
156
+ const { awsService } = providerOptions ;
157
+ const method =
158
+ c . get ( 'method' ) || // method set specifically into context
159
+ getMethod ( fn as endpointStrings , transformedRequestUrl , c ) ; // method calculated
160
+ const service = awsService || getService ( fn as endpointStrings ) ;
148
161
149
- const headers : Record < string , string > = {
150
- 'content-type' : 'application/json' ,
151
- } ;
162
+ let headers : Record < string , string > = { } ;
152
163
153
- if ( method === 'PUT' || method === 'GET' ) {
164
+ if ( fn === 'proxy' && service !== 'bedrock' ) {
165
+ headers = { ...( requestHeaders ?? { } ) } ;
166
+ } else {
167
+ headers = {
168
+ 'content-type' : 'application/json' ,
169
+ } ;
170
+ }
171
+
172
+ if ( ( method === 'PUT' || method === 'GET' ) && fn !== 'proxy' ) {
154
173
delete headers [ 'content-type' ] ;
155
174
}
156
175
@@ -160,7 +179,8 @@ const BedrockAPIConfig: BedrockAPIConfigInterface = {
160
179
await providerAssumedRoleCredentials ( c , providerOptions ) ;
161
180
}
162
181
163
- let finalRequestBody = transformedRequestBody ;
182
+ let finalRequestBody =
183
+ fn === 'proxy' ? gatewayRequestBody : transformedRequestBody ;
164
184
165
185
if ( [ 'cancelFinetune' , 'cancelBatch' ] . includes ( fn as endpointStrings ) ) {
166
186
// Cancel doesn't require any body, but fetch is sending empty body, to match the signature this block is required.
@@ -183,7 +203,6 @@ const BedrockAPIConfig: BedrockAPIConfigInterface = {
183
203
fn,
184
204
gatewayRequestBodyJSON : gatewayRequestBody ,
185
205
gatewayRequestURL,
186
- c,
187
206
} ) => {
188
207
if ( fn === 'retrieveFile' ) {
189
208
const fileId = decodeURIComponent (
0 commit comments