import { Lifecycle , Request , ResponseObject , ResponseToolkit as HapiResponseToolkit , } from '@hapi/hapi' ; import Boom from '@hapi/boom' ; import { Logger } from '../../logging' ; import { HapiResponseAdapter , KibanaRequest , ResponseHeaders } from '../router' ; enum ResultType { render = 'render' , next = 'next' } interface Render { type : ResultType . render ; body : string ; headers ? : ResponseHeaders ; } interface Next { type : ResultType . next ; headers ? : ResponseHeaders ; } internal type OnPreResponseResult = Render | Next ; public export interface OnPreResponseRender { /** additional headers to attach to the response */ headers ? : ResponseHeaders ; /** the body to use in the response */ body : string ; } public export interface OnPreResponseExtensions { /** additional headers to attach to the response */ headers ? : ResponseHeaders ; } public export interface OnPreResponseInfo { statusCode : number ; } const preResponseResult = { render ( responseRender ) { return { type : ResultType . render , body : responseRender . body , headers : responseRender ?. headers } ; } , isRender ( result ) { return result && result . type === ResultType . render ; } , next ( responseExtensions ? ) { return { type : ResultType . next , headers : responseExtensions ?. headers } ; } , isNext ( result ) { return result && result . type === ResultType . next ; } , } ; public export interface OnPreResponseToolkit { /** To override the response with a different body */ render : ( responseRender : OnPreResponseRender ) => OnPreResponseResult ; /** To pass request to the next handler */ next : ( responseExtensions ? : OnPreResponseExtensions ) => OnPreResponseResult ; } const toolkit = { render : preResponseResult . render , next : preResponseResult . next , } ; /**
 * See  OnPreRoutingToolkit .
 *  public export type OnPreResponseHandler = ( request : KibanaRequest , preResponse : OnPreResponseInfo , toolkit : OnPreResponseToolkit ) => OnPreResponseResult | Promise < OnPreResponseResult > ; public param fn export function adoptToHapiOnPreResponseFormat ( fn , log ) { return async function interceptPreResponse ( request , responseToolkit ) : Promise < Lifecycle . ReturnValue > { const response = request . response ; try { if ( response ) { const statusCode = isBoom ( response ) ? response . output . statusCode : response . statusCode ; const result = await fn ( KibanaRequest . from ( request ) , { statusCode } , toolkit ) ; if ( preResponseResult . isNext ( result ) ) { if ( result . headers ) { if ( isBoom ( response ) ) { findHeadersIntersection ( response . output . headers as { [ key ] : string ; } , result . headers , log ) ; response . output . headers = { ... response . output . headers , ... ( result . headers as any ) , } ; } else { findHeadersIntersection ( response . headers , result . headers , log ) ; setHeaders ( response , result . headers ) ; } } } else if ( preResponseResult . isRender ( result ) ) { const overriddenResponse = responseToolkit . response ( result . body ) . code ( statusCode ) ; const originalHeaders = isBoom ( response ) ? response . output . headers : response . headers ; setHeaders ( overriddenResponse , originalHeaders as { [ key ] : string ; } ) ; if ( result . headers ) { setHeaders ( overriddenResponse , result . headers ) ; } return overriddenResponse ; } else { throw new Error ( `Unexpected result from OnPreResponse. Expected OnPreResponseResult, but given: ${ result }.` ) ; } } } catch ( error ) { log . error ( error ) ; const hapiResponseAdapter = new HapiResponseAdapter ( responseToolkit ) ; return hapiResponseAdapter . toInternalError ( ) ; } return responseToolkit . continue ; } ; } function isBoom ( response ) { return response instanceof Boom . Boom ; } function setHeaders ( response , headers ) { for ( const [ headerName , headerValue ] of Object . entries ( headers ) ) { response . header ( headerName , headerValue as any ) ; } } function findHeadersIntersection ( responseHeaders , headers , log ) { Object . keys ( headers ) . forEach ( ( headerName ) => { if ( Reflect . has ( responseHeaders , headerName ) ) { log . warn ( `onPreResponseHandler rewrote a response header [${ headerName }].` ) ; } } ) ; }