@@ -40,6 +40,85 @@ function getPsiUrl(url, env) {
40
40
return `https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed?url=${ encodeURIComponent ( url . toString ( ) ) } &key=${ env . PSI_KEY } &strategy=desktop&category=performance` ;
41
41
}
42
42
43
+ /**
44
+ * Validates a domainkey against the RUM Bundler API
45
+ * @param {string } domain the domain, e.g. "www.example.com"
46
+ * @param {string } key the domainkey to validate
47
+ * @returns {Promise<boolean> } true if the domainkey is valid, exception otherwise
48
+ */
49
+ async function isDomainkeyValid ( domain , key ) {
50
+ if ( ! domain || ! key ) {
51
+ throw new Error ( 'invalid domain or key' ) ;
52
+ }
53
+ try {
54
+ const beurl = new URL ( `https://rum.fastly-aem.page/domains/${ domain } ` ) ;
55
+ beurl . searchParams . set ( 'domainkey' , key ) ;
56
+
57
+ const beresp = fetch ( beurl , {
58
+ cf : {
59
+ // keep the auth in cache for 10 minutes
60
+ cacheTtl : 600 ,
61
+ cacheEverything : true ,
62
+ } ,
63
+ } ) ;
64
+ if ( ! beresp . ok ) {
65
+ throw new Error ( 'invalid domain or key' ) ;
66
+ }
67
+ return true ;
68
+ } catch ( e ) {
69
+ throw new Error ( 'invalid domain or key' , e ) ;
70
+ }
71
+ }
72
+
73
+ async function handleCorsRoute ( request , env ) {
74
+ const url = new URL ( req . url ) ;
75
+ const params = new URLSearchParams ( url . search ) ;
76
+
77
+ const beurl = new URL ( params . get ( 'url' ) ) ;
78
+ const domainkey = params . get ( 'domainkey' ) ;
79
+
80
+ try {
81
+ await isDomainkeyValid ( beurl . hostname , domainkey ) ;
82
+ const beresp = await fetch ( beurl , {
83
+ cf : {
84
+ cacheTtl : 3600 ,
85
+ cacheEverything : true ,
86
+ } ,
87
+ } ) ;
88
+ // if not ok, or response is neither HTML or JSON, return 404
89
+ if ( ! beresp . ok
90
+ || ! beresp . headers . get ( 'content-type' ) . includes ( 'html' )
91
+ || ! beresp . headers . get ( 'content-type' ) . includes ( 'json' ) ) {
92
+ return new Response ( '' , {
93
+ status : 404 ,
94
+ headers : {
95
+ 'x-error' : 'not found' ,
96
+ } ,
97
+ } ) ;
98
+ }
99
+ const headers = new Headers ( beresp . headers ) ;
100
+ headers . set ( 'access-control-allow-origin' , '*' ) ;
101
+ headers . set ( 'access-control-allow-credentials' , 'true' ) ;
102
+ headers . set ( 'access-control-allow-headers' , 'Content-Type' ) ;
103
+ headers . set ( 'access-control-allow-methods' , 'GET, POST, OPTIONS' ) ;
104
+ headers . set ( 'access-control-max-age' , '86400' ) ;
105
+
106
+ // allow CORS
107
+ return new Response ( beresp . body , {
108
+ status : 200 ,
109
+ headers
110
+ } ) ;
111
+ } catch ( e ) {
112
+ // return 503
113
+ return new Response ( '' , {
114
+ status : 503 ,
115
+ headers : {
116
+ 'x-error' : e . message ,
117
+ } ,
118
+ } ) ;
119
+ }
120
+ }
121
+
43
122
/**
44
123
* Check if image exists and is not pending/failed
45
124
* @param {string } key
@@ -324,6 +403,10 @@ const handleRequest = async (request, env, ctx) => {
324
403
return handleImageRoute ( request , env , ctx ) ;
325
404
}
326
405
406
+ if ( url . pathname . startsWith ( '/tools/rum/_cors' ) ) {
407
+ return handleCorsRoute ( request , env , ctx ) ;
408
+ }
409
+
327
410
url . hostname = 'main--helix-website--adobe.aem.live' ;
328
411
const req = new Request ( url , request ) ;
329
412
const resp = await fetch ( req , {
0 commit comments