@@ -4,112 +4,117 @@ const SHOULD_IGNORE_OPTIONS_REQUESTS = false;
44
55declare var IntegrationConfigKV : string ;
66declare var Response : any ;
7- declare var Request : any ;
87
98import { KnownUser , Utils } from 'queueit-knownuser'
109import CloudflareHttpContextProvider from './contextProvider'
1110import { addKUPlatformVersion , configureKnownUserHashing , getParameterByName } from "./queueitHelpers" ;
1211import { getIntegrationConfig , tryStoreIntegrationConfig } from "./integrationConfigProvider" ;
1312
14- let httpContextProvider : CloudflareHttpContextProvider | null ;
15- let sendNoCacheHeaders : boolean = false ;
13+ export default class QueueITRequestResponseHandler {
14+ private httpContextProvider : CloudflareHttpContextProvider | null ;
15+ private sendNoCacheHeaders : boolean = false ;
1616
17- export async function onQueueItRequest ( request : any , customerId : string , secretKey : string , readRequestBody ?: boolean ) {
18- if ( isIgnored ( request ) ) {
19- return null ;
17+ constructor ( private customerId : string , private secretKey : string , private readRequestBody : boolean = false ) {
2018 }
2119
22- if ( request . url . indexOf ( '__push_queueit_config' ) > 0 ) {
23- const result = await tryStoreIntegrationConfig ( request , IntegrationConfigKV , secretKey ) ;
24- return new Response ( result ? "Success!" : "Fail!" , result ? undefined : { status : 400 } ) ;
25- }
20+ async onClientRequest ( request : any ) {
21+ if ( isIgnored ( request ) ) {
22+ return null ;
23+ }
2624
27- try {
28- const integrationConfigJson = await getIntegrationConfig ( IntegrationConfigKV ) || "" ;
25+ if ( request . url . indexOf ( '__push_queueit_config' ) > 0 ) {
26+ const result = await tryStoreIntegrationConfig ( request , IntegrationConfigKV , this . secretKey ) ;
27+ return new Response ( result ? "Success!" : "Fail!" , result ? undefined : { status : 400 } ) ;
28+ }
2929
30- configureKnownUserHashing ( Utils ) ;
30+ try {
31+ const integrationConfigJson = await getIntegrationConfig ( IntegrationConfigKV ) || "" ;
3132
32- let bodyText = "" ;
33- if ( readRequestBody ) {
34- //reading maximum 2k characters of body to do the mathcing
35- bodyText = ( await request . clone ( ) . text ( ) || "" ) . substring ( 0 , 2048 ) ;
36- }
37- httpContextProvider = new CloudflareHttpContextProvider ( request , bodyText ) ;
38-
39- const queueitToken = getQueueItToken ( request , httpContextProvider ) ;
40- const requestUrl = request . url ;
41- const requestUrlWithoutToken = requestUrl . replace ( new RegExp ( "([\?&])(" + KnownUser . QueueITTokenKey + "=[^&]*)" , 'i' ) , "" ) ;
42- // The requestUrlWithoutToken is used to match Triggers and as the Target url (where to return the users to).
43- // It is therefor important that this is exactly the url of the users browsers. So, if your webserver is
44- // behind e.g. a load balancer that modifies the host name or port, reformat requestUrlWithoutToken before proceeding.
45-
46-
47- const validationResult = KnownUser . validateRequestByIntegrationConfig (
48- requestUrlWithoutToken , queueitToken , integrationConfigJson ,
49- customerId , secretKey , httpContextProvider ) ;
50-
51- if ( validationResult . doRedirect ( ) ) {
52- if ( validationResult . isAjaxResult ) {
53- const response = new Response ( ) ;
54- const headerKey = validationResult . getAjaxQueueRedirectHeaderKey ( ) ;
55- const queueRedirectUrl = validationResult . getAjaxRedirectUrl ( ) ;
56-
57- // In case of ajax call send the user to the queue by sending a custom queue-it header and redirecting user to queue from javascript
58- response . headers . set ( headerKey , addKUPlatformVersion ( queueRedirectUrl ) ) ;
59- response . headers . set ( 'Access-Control-Expose-Headers' , headerKey )
60- sendNoCacheHeaders = true ;
61- return response ;
62- } else {
63- let responseResult = new Response ( null , { status : 302 } ) ;
33+ configureKnownUserHashing ( Utils ) ;
6434
65- // Send the user to the queue - either because hash was missing or because is was invalid
66- responseResult . headers . set ( 'Location' , addKUPlatformVersion ( validationResult . redirectUrl ) ) ;
67- sendNoCacheHeaders = true ;
68- return responseResult
35+ let bodyText = "" ;
36+ if ( this . readRequestBody ) {
37+ //reading maximum 2k characters of body to do the mathcing
38+ bodyText = ( await request . clone ( ) . text ( ) || "" ) . substring ( 0 , 2048 ) ;
6939 }
70- } else {
71- // Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token
72- if ( requestUrl !== requestUrlWithoutToken && validationResult . actionType === 'Queue' ) {
73- let response = new Response ( null , { status : 302 } ) ;
74- response . headers . set ( 'Location' , requestUrlWithoutToken ) ;
75- sendNoCacheHeaders = true ;
76- return response ;
40+ this . httpContextProvider = new CloudflareHttpContextProvider ( request , bodyText ) ;
41+
42+ const queueitToken = getQueueItToken ( request , this . httpContextProvider ) ;
43+ const requestUrl = request . url ;
44+ const requestUrlWithoutToken = requestUrl . replace ( new RegExp ( "([\?&])(" + KnownUser . QueueITTokenKey + "=[^&]*)" , 'i' ) , "" ) ;
45+ // The requestUrlWithoutToken is used to match Triggers and as the Target url (where to return the users to).
46+ // It is therefor important that this is exactly the url of the users browsers. So, if your webserver is
47+ // behind e.g. a load balancer that modifies the host name or port, reformat requestUrlWithoutToken before proceeding.
48+
49+ const validationResult = KnownUser . validateRequestByIntegrationConfig (
50+ requestUrlWithoutToken , queueitToken , integrationConfigJson ,
51+ this . customerId , this . secretKey , this . httpContextProvider ) ;
52+
53+ if ( validationResult . doRedirect ( ) ) {
54+ if ( validationResult . isAjaxResult ) {
55+ const response = new Response ( ) ;
56+ const headerKey = validationResult . getAjaxQueueRedirectHeaderKey ( ) ;
57+ const queueRedirectUrl = validationResult . getAjaxRedirectUrl ( ) ;
58+
59+ // In case of ajax call send the user to the queue by sending a custom queue-it header and redirecting user to queue from javascript
60+ response . headers . set ( headerKey , addKUPlatformVersion ( queueRedirectUrl ) ) ;
61+ response . headers . set ( 'Access-Control-Expose-Headers' , headerKey )
62+ this . sendNoCacheHeaders = true ;
63+ return response ;
64+ } else {
65+ let responseResult = new Response ( null , { status : 302 } ) ;
66+
67+ // Send the user to the queue - either because hash was missing or because is was invalid
68+ responseResult . headers . set ( 'Location' , addKUPlatformVersion ( validationResult . redirectUrl ) ) ;
69+ this . sendNoCacheHeaders = true ;
70+ return responseResult
71+ }
7772 } else {
78- // lets caller decides the next step
79- return null ;
73+ // Request can continue - we remove queueittoken form querystring parameter to avoid sharing of user specific token
74+ if ( requestUrl !== requestUrlWithoutToken && validationResult . actionType === 'Queue' ) {
75+ let response = new Response ( null , { status : 302 } ) ;
76+ response . headers . set ( 'Location' , requestUrlWithoutToken ) ;
77+ this . sendNoCacheHeaders = true ;
78+ return response ;
79+ } else {
80+ // lets caller decides the next step
81+ return null ;
82+ }
8083 }
81- }
8284
83- } catch ( e ) {
84- // There was an error validationg the request
85- // Use your own logging framework to log the Exception
86- if ( console && console . log ) {
87- console . log ( "ERROR:" + e ) ;
85+ } catch ( e ) {
86+ // There was an error validationg the request
87+ // Use your own logging framework to log the Exception
88+ if ( console && console . log ) {
89+ console . log ( "ERROR:" + e ) ;
90+ }
91+ this . httpContextProvider ! . isError = true ;
92+ // lets caller decides the next step
93+ return null ;
8894 }
89- httpContextProvider ! . isError = true ;
90- // lets caller decides the next step
91- return null ;
9295 }
93- }
9496
95- export async function onQueueItResponse ( response : any ) {
96- let newResponse = new Response ( response . body , response ) ;
97- newResponse . headers . set ( QUEUEIT_CONNECTOR_EXECUTED_HEADER_NAME , 'cloudflare' ) ;
97+ async onClientResponse ( response : any ) {
98+ let newResponse = new Response ( response . body , response ) ;
99+ newResponse . headers . set ( QUEUEIT_CONNECTOR_EXECUTED_HEADER_NAME , 'cloudflare' ) ;
98100
99- if ( httpContextProvider ) {
100- if ( httpContextProvider . outputCookie ) {
101- newResponse . headers . append ( "Set-Cookie" , httpContextProvider . outputCookie ) ;
101+ if ( this . httpContextProvider ) {
102+ const outputCookie = this . httpContextProvider . getOutputCookie ( ) ;
103+ if ( outputCookie ) {
104+ newResponse . headers . append ( "Set-Cookie" , outputCookie ) ;
105+ }
106+ if ( this . httpContextProvider . isError ) {
107+ newResponse . headers . append ( QUEUEIT_FAILED_HEADERNAME , "true" ) ;
108+ }
102109 }
103- if ( httpContextProvider . isError ) {
104- newResponse . headers . append ( QUEUEIT_FAILED_HEADERNAME , "true" ) ;
110+
111+ if ( this . sendNoCacheHeaders ) {
112+ addNoCacheHeaders ( newResponse ) ;
105113 }
106- }
107114
108- if ( sendNoCacheHeaders ) {
109- addNoCacheHeaders ( newResponse ) ;
115+ return newResponse ;
110116 }
111117
112- return newResponse ;
113118}
114119
115120function isIgnored ( request : any ) {
0 commit comments