@@ -127,9 +127,12 @@ export class PostHandler extends BaseHandler {
127127
128128 let isFinal : boolean
129129 let url : string
130- let headers : {
131- 'Upload-Offset' ?: string
132- 'Upload-Expires' ?: string
130+
131+ //Recommended response defaults
132+ const responseData = {
133+ status : 201 ,
134+ headers : { } as Record < string , string | number > ,
135+ body : '' ,
133136 }
134137
135138 try {
@@ -139,14 +142,13 @@ export class PostHandler extends BaseHandler {
139142 this . emit ( EVENTS . POST_CREATE , req , res , upload , url )
140143
141144 isFinal = upload . size === 0 && ! upload . sizeIsDeferred
142- headers = { }
143145
144146 // The request MIGHT include a Content-Type header when using creation-with-upload extension
145147 if ( validateHeader ( 'content-type' , req . headers [ 'content-type' ] ) ) {
146148 const bodyMaxSize = await this . calculateMaxBodySize ( req , upload , maxFileSize )
147149 const newOffset = await this . writeToStore ( req , upload , bodyMaxSize , context )
148150
149- headers [ 'Upload-Offset' ] = newOffset . toString ( )
151+ responseData . headers [ 'Upload-Offset' ] = newOffset . toString ( )
150152 isFinal = newOffset === Number . parseInt ( upload_length as string , 10 )
151153 upload . offset = newOffset
152154 }
@@ -159,7 +161,24 @@ export class PostHandler extends BaseHandler {
159161
160162 if ( isFinal && this . options . onUploadFinish ) {
161163 try {
162- res = await this . options . onUploadFinish ( req , res , upload )
164+ const resOrObject = await this . options . onUploadFinish ( req , res , upload )
165+ // Backwards compatibility, remove in next major
166+ // Ugly check because we can't use `instanceof` because we mock the instance in tests
167+ if (
168+ typeof ( resOrObject as http . ServerResponse ) . write === 'function' &&
169+ typeof ( resOrObject as http . ServerResponse ) . writeHead === 'function'
170+ ) {
171+ res = resOrObject as http . ServerResponse
172+ } else {
173+ // Ugly types because TS only understands instanceof
174+ type ExcludeServerResponse < T > = T extends http . ServerResponse ? never : T
175+ const obj = resOrObject as ExcludeServerResponse < typeof resOrObject >
176+ res = obj . res
177+ if ( obj . status_code ) responseData . status = obj . status_code
178+ if ( obj . body ) responseData . body = obj . body
179+ if ( obj . headers )
180+ responseData . headers = Object . assign ( obj . headers , responseData . headers )
181+ }
163182 } catch ( error ) {
164183 log ( `onUploadFinish: ${ error . body } ` )
165184 throw error
@@ -178,13 +197,26 @@ export class PostHandler extends BaseHandler {
178197 if ( created . offset !== Number . parseInt ( upload_length as string , 10 ) ) {
179198 const creation = new Date ( upload . creation_date )
180199 // Value MUST be in RFC 7231 datetime format
181- headers [ 'Upload-Expires' ] = new Date (
200+ responseData . headers [ 'Upload-Expires' ] = new Date (
182201 creation . getTime ( ) + this . store . getExpiration ( )
183202 ) . toUTCString ( )
184203 }
185204 }
186205
187- const writtenRes = this . write ( res , 201 , { Location : url , ...headers } )
206+ //Only append Location header if its valid for the final http status (201 or 3xx)
207+ if (
208+ responseData . status === 201 ||
209+ ( responseData . status >= 300 && responseData . status < 400 )
210+ ) {
211+ responseData . headers [ 'Location' ] = url
212+ }
213+
214+ const writtenRes = this . write (
215+ res ,
216+ responseData . status ,
217+ responseData . headers ,
218+ responseData . body
219+ )
188220
189221 if ( isFinal ) {
190222 this . emit ( EVENTS . POST_FINISH , req , writtenRes , upload )
0 commit comments