@@ -6,7 +6,6 @@ import { parseSetCookieHeader } from "@opennextjs/core/http/util.js";
66import { extractHostFromHeaders } from "@opennextjs/core/overrides/converters/utils.js" ;
77import type { InternalEvent , InternalResult , MiddlewareResult } from "@opennextjs/core/types/open-next.js" ;
88import type { Converter } from "@opennextjs/core/types/overrides.js" ;
9- import { fromReadableStream } from "@opennextjs/core/utils/stream.js" ;
109import type {
1110 CloudFrontCustomOrigin ,
1211 CloudFrontHeaders ,
@@ -15,6 +14,8 @@ import type {
1514 CloudFrontRequestResult ,
1615} from "aws-lambda" ;
1716
17+ import { createBufferedStreamCreator } from "./response-stream.js" ;
18+
1819const cloudfrontBlacklistedHeaders = [
1920 // Disallowed headers, see: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html#function-restrictions-disallowed-headers
2021 "connection" ,
@@ -129,67 +130,83 @@ function convertToCloudfrontHeaders(headers: Record<string, OutgoingHttpHeader>,
129130 return cloudfrontHeaders ;
130131}
131132
132- async function convertToCloudFrontRequestResult (
133- result : InternalResult | MiddlewareResult ,
133+ async function convertMiddlewareResult (
134+ result : MiddlewareResult ,
134135 originalRequest : CloudFrontRequestEvent
135136) : Promise < CloudFrontRequestResult > {
136- if ( result . type === "middleware" ) {
137- const { method, clientIp, origin } = originalRequest . Records [ 0 ] . cf . request ;
138- const responseHeaders = result . internalEvent . headers ;
139-
140- // Handle external rewrite
141-
142- let customOrigin = origin ?. custom as CloudFrontCustomOrigin ;
143- let host = responseHeaders . host ?? responseHeaders . Host ;
144- if ( result . origin ) {
145- customOrigin = {
146- ...customOrigin ,
147- domainName : result . origin . host ,
148- port : result . origin . port ?? 443 ,
149- protocol : result . origin . protocol ?? "https" ,
150- customHeaders : { } ,
151- } ;
152- host = result . origin . host ;
153- }
154-
155- const response : CloudFrontRequest = {
156- clientIp,
157- method,
158- uri : result . internalEvent . rawPath ,
159- querystring : convertToQueryString ( result . internalEvent . query ) . replace ( "?" , "" ) ,
160- headers : convertToCloudfrontHeaders ( {
161- ...responseHeaders ,
162- host,
163- } ) ,
164- origin : origin ?. custom
165- ? {
166- custom : customOrigin ,
167- }
168- : origin ,
137+ const { method, clientIp, origin } = originalRequest . Records [ 0 ] . cf . request ;
138+ const responseHeaders = result . internalEvent . headers ;
139+
140+ // Handle external rewrite
141+
142+ let customOrigin = origin ?. custom as CloudFrontCustomOrigin ;
143+ let host = responseHeaders . host ?? responseHeaders . Host ;
144+ if ( result . origin ) {
145+ customOrigin = {
146+ ...customOrigin ,
147+ domainName : result . origin . host ,
148+ port : result . origin . port ?? 443 ,
149+ protocol : result . origin . protocol ?? "https" ,
150+ customHeaders : { } ,
169151 } ;
152+ host = result . origin . host ;
153+ }
170154
171- debug ( "response rewrite" , response ) ;
155+ const response : CloudFrontRequest = {
156+ clientIp,
157+ method,
158+ uri : result . internalEvent . rawPath ,
159+ querystring : convertToQueryString ( result . internalEvent . query ) . replace ( "?" , "" ) ,
160+ headers : convertToCloudfrontHeaders ( {
161+ ...responseHeaders ,
162+ host,
163+ } ) ,
164+ origin : origin ?. custom
165+ ? {
166+ custom : customOrigin ,
167+ }
168+ : origin ,
169+ } ;
172170
173- return response ;
174- }
171+ debug ( "response rewrite" , response ) ;
175172
176- const body = await fromReadableStream ( result . body , result . isBase64Encoded ) ;
177- const responseHeaders = result . headers ;
173+ return response ;
174+ }
178175
176+ function convertToCloudFrontRequestResult (
177+ prelude : { statusCode : number ; cookies : string [ ] ; headers : Record < string , string > } ,
178+ body : Buffer ,
179+ isBase64Encoded : boolean
180+ ) : CloudFrontRequestResult {
181+ const responseHeaders = {
182+ ...prelude . headers ,
183+ ...( prelude . cookies . length > 0 ? { "set-cookie" : prelude . cookies } : { } ) ,
184+ } ;
179185 const response : CloudFrontRequestResult = {
180- status : result . statusCode . toString ( ) ,
186+ status : prelude . statusCode . toString ( ) ,
181187 statusDescription : "OK" ,
182188 headers : convertToCloudfrontHeaders ( responseHeaders , true ) ,
183- bodyEncoding : result . isBase64Encoded ? "base64" : "text" ,
184- body,
189+ bodyEncoding : isBase64Encoded ? "base64" : "text" ,
190+ body : body . toString ( isBase64Encoded ? "base64" : "utf8" ) ,
185191 } ;
186192
187193 debug ( response ) ;
188194 return response ;
189195}
190196
191197export default {
192- convertFrom : convertFromCloudFrontRequestEvent ,
193- convertTo : convertToCloudFrontRequestResult ,
198+ convertFrom : ( event ) => convertFromCloudFrontRequestEvent ( event as CloudFrontRequestEvent ) ,
199+ convertTo : async ( event ) => {
200+ const { streamCreator, output } = createBufferedStreamCreator ( convertToCloudFrontRequestResult ) ;
201+ return {
202+ type : "stream" as const ,
203+ streamCreator,
204+ output,
205+ data : async ( result ) =>
206+ result . type === "middleware"
207+ ? convertMiddlewareResult ( result , event as CloudFrontRequestEvent )
208+ : undefined ,
209+ } ;
210+ } ,
194211 name : "aws-cloudfront" ,
195- } as Converter ;
212+ } satisfies Converter < InternalEvent , InternalResult | MiddlewareResult > ;
0 commit comments