1
1
import { ProviderConfig , RequestHandler } from '../types' ;
2
2
import {
3
+ generateSignedURL ,
3
4
getModelAndProvider ,
4
5
GoogleResponseHandler ,
5
6
vertexRequestLineHandler ,
@@ -49,7 +50,11 @@ export const GoogleFileUploadRequestHandler: RequestHandler<
49
50
vertexBatchEndpoint = BatchEndpoints . CHAT_COMPLETIONS , //default to inference endpoint
50
51
} = providerOptions ;
51
52
52
- if ( ! vertexModelName || ! vertexStorageBucketName ) {
53
+ let purpose = requestHeaders [ 'x-portkey-file-purpose' ] ?? '' ;
54
+ if (
55
+ ( purpose === 'upload' ? false : ! vertexModelName ) ||
56
+ ! vertexStorageBucketName
57
+ ) {
53
58
return GoogleResponseHandler (
54
59
'Invalid request, please provide `x-portkey-provider-model` and `x-portkey-vertex-storage-bucket-name` in the request headers' ,
55
60
400
@@ -73,73 +78,79 @@ export const GoogleFileUploadRequestHandler: RequestHandler<
73
78
}
74
79
75
80
let isPurposeHeader = false ;
76
- let purpose = '' ;
81
+ let transformStream : ReadableStream < any > | TransformStream < any , any > =
82
+ requestBody ;
83
+ let uploadMethod = 'PUT' ;
77
84
// Create a reusable line splitter stream
78
85
const lineSplitter = createLineSplitter ( ) ;
79
86
80
- // Transform stream to process each complete line.
81
- const transformStream = new TransformStream ( {
82
- transform : function ( chunk , controller ) {
83
- let buffer ;
84
- try {
85
- const _chunk = chunk . toString ( ) ;
86
-
87
- const match = _chunk . match ( / n a m e = " ( [ ^ " ] + ) " / ) ;
88
- const headerKey = match ? match [ 1 ] : null ;
89
-
90
- if ( headerKey && headerKey === 'purpose' ) {
91
- isPurposeHeader = true ;
92
- return ;
93
- }
94
-
95
- if ( isPurposeHeader && _chunk ?. length > 0 && ! purpose ) {
96
- isPurposeHeader = false ;
97
- purpose = _chunk . trim ( ) ;
98
- return ;
99
- }
100
-
101
- if ( ! _chunk ) {
102
- return ;
103
- }
104
-
105
- const json = JSON . parse ( chunk . toString ( ) ) ;
106
-
107
- if ( json && ! purpose ) {
108
- // Close the stream.
109
- controller . terminate ( ) ;
87
+ if ( purpose === 'upload' ) {
88
+ uploadMethod = 'POST' ;
89
+ } else {
90
+ // Transform stream to process each complete line.
91
+ transformStream = new TransformStream ( {
92
+ transform : function ( chunk , controller ) {
93
+ let buffer ;
94
+ try {
95
+ const _chunk = chunk . toString ( ) ;
96
+
97
+ const match = _chunk . match ( / n a m e = " ( [ ^ " ] + ) " / ) ;
98
+ const headerKey = match ? match [ 1 ] : null ;
99
+
100
+ if ( headerKey && headerKey === 'purpose' ) {
101
+ isPurposeHeader = true ;
102
+ return ;
103
+ }
104
+
105
+ if ( isPurposeHeader && _chunk ?. length > 0 && ! purpose ) {
106
+ isPurposeHeader = false ;
107
+ purpose = _chunk . trim ( ) ;
108
+ return ;
109
+ }
110
+
111
+ if ( ! _chunk ) {
112
+ return ;
113
+ }
114
+
115
+ const json = JSON . parse ( chunk . toString ( ) ) ;
116
+
117
+ if ( json && ! purpose ) {
118
+ // Close the stream.
119
+ controller . terminate ( ) ;
120
+ }
121
+
122
+ const toTranspose = purpose === 'batch' ? json . body : json ;
123
+ const transformedBody = transformUsingProviderConfig (
124
+ providerConfig ,
125
+ toTranspose
126
+ ) ;
127
+
128
+ delete transformedBody [ 'model' ] ;
129
+
130
+ const bufferTransposed = vertexRequestLineHandler (
131
+ purpose ,
132
+ vertexBatchEndpoint ,
133
+ transformedBody ,
134
+ json [ 'custom_id' ]
135
+ ) ;
136
+
137
+ buffer = JSON . stringify ( bufferTransposed ) ;
138
+ } catch {
139
+ buffer = null ;
140
+ } finally {
141
+ if ( buffer ) {
142
+ controller . enqueue ( encoder . encode ( buffer + '\n' ) ) ;
143
+ }
110
144
}
111
-
112
- const toTranspose = purpose === 'batch' ? json . body : json ;
113
- const transformedBody = transformUsingProviderConfig (
114
- providerConfig ,
115
- toTranspose
116
- ) ;
117
-
118
- delete transformedBody [ 'model' ] ;
119
-
120
- const bufferTransposed = vertexRequestLineHandler (
121
- purpose ,
122
- vertexBatchEndpoint ,
123
- transformedBody ,
124
- json [ 'custom_id' ]
125
- ) ;
126
-
127
- buffer = JSON . stringify ( bufferTransposed ) ;
128
- } catch {
129
- buffer = null ;
130
- } finally {
131
- if ( buffer ) {
132
- controller . enqueue ( encoder . encode ( buffer + '\n' ) ) ;
133
- }
134
- }
135
- } ,
136
- flush ( controller ) {
137
- controller . terminate ( ) ;
138
- } ,
139
- } ) ;
145
+ } ,
146
+ flush ( controller ) {
147
+ controller . terminate ( ) ;
148
+ } ,
149
+ } ) ;
150
+ requestBody . pipeThrough ( lineSplitter ) . pipeTo ( transformStream . writable ) ;
151
+ }
140
152
141
153
// Pipe the node stream through our line splitter and into the transform stream.
142
- requestBody . pipeThrough ( lineSplitter ) . pipeTo ( transformStream . writable ) ;
143
154
144
155
const providerHeaders = await GoogleApiConfig . headers ( {
145
156
c,
@@ -151,15 +162,36 @@ export const GoogleFileUploadRequestHandler: RequestHandler<
151
162
} ) ;
152
163
153
164
const encodedFile = encodeURIComponent ( objectKey ?? '' ) ;
154
- const url = `https://storage.googleapis.com/${ vertexStorageBucketName } /${ encodedFile } ` ;
165
+ let url ;
166
+ if ( uploadMethod !== 'POST' ) {
167
+ url = `https://storage.googleapis.com/${ vertexStorageBucketName } /${ encodedFile } ` ;
168
+ } else {
169
+ url = await generateSignedURL (
170
+ providerOptions . vertexServiceAccountJson ?? { } ,
171
+ vertexStorageBucketName ,
172
+ objectKey ,
173
+ 10 * 60 ,
174
+ 'POST' ,
175
+ c . req . param ( ) ,
176
+ { }
177
+ ) ;
178
+ }
155
179
156
180
const options = {
157
- body : transformStream . readable ,
181
+ body :
182
+ uploadMethod === 'POST'
183
+ ? ( transformStream as ReadableStream < any > )
184
+ : ( transformStream as TransformStream ) . readable ,
158
185
headers : {
159
- Authorization : providerHeaders . Authorization ,
160
- 'Content-Type' : 'application/octet-stream' ,
186
+ ...( uploadMethod !== 'POST'
187
+ ? { Authorization : providerHeaders . Authorization }
188
+ : { } ) ,
189
+ 'Content-Type' :
190
+ uploadMethod === 'POST'
191
+ ? requestHeaders [ 'content-type' ]
192
+ : 'application/octet-stream' ,
161
193
} ,
162
- method : 'PUT' ,
194
+ method : uploadMethod ,
163
195
duplex : 'half' ,
164
196
} ;
165
197
0 commit comments