@quintype/framework 7.34.7-handle-500-issue.2 → 7.34.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/package.json +2 -2
- package/server/handlers/cdn-caching.js +1 -1
- package/server/handlers/isomorphic-handler.js +1 -7
- package/test/integration/custom-route-handler-test.js +44 -13
- package/test/integration/isomorphic-handler-test.js +21 -8
- package/test/integration/url-redirect-test.js +40 -10
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [7.34.7](https://github.com/quintype/quintype-node-framework/compare/v7.34.6...v7.34.7) (2025-11-21)
|
|
6
|
+
|
|
5
7
|
### [7.34.6](https://github.com/quintype/quintype-node-framework/compare/v7.34.4...v7.34.6) (2025-10-17)
|
|
6
8
|
|
|
7
9
|
### [7.34.5](https://github.com/quintype/quintype-node-framework/compare/v7.34.4...v7.34.5) (2025-09-01)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quintype/framework",
|
|
3
|
-
"version": "7.34.7
|
|
3
|
+
"version": "7.34.7",
|
|
4
4
|
"description": "Libraries to help build Quintype Node.js apps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@ampproject/toolbox-optimizer": "2.8.3",
|
|
34
34
|
"@grpc/grpc-js": "^1.12.5",
|
|
35
35
|
"@jsdoc/salty": "^0.2.9",
|
|
36
|
-
"@quintype/amp": "^2.22.
|
|
36
|
+
"@quintype/amp": "^2.22.8",
|
|
37
37
|
"@quintype/backend": "^2.7.0",
|
|
38
38
|
"@quintype/components": "^3.5.0",
|
|
39
39
|
"@quintype/prerender-node": "^3.2.26",
|
|
@@ -42,7 +42,7 @@ exports.addCacheHeadersToResult = function addCacheHeadersToResult({
|
|
|
42
42
|
} else {
|
|
43
43
|
res.setHeader(
|
|
44
44
|
"Cache-Control",
|
|
45
|
-
`public,max-age=${maxAge},s-maxage
|
|
45
|
+
`public,max-age=${maxAge},s-maxage=${sMaxAge},stale-while-revalidate=1000,stale-if-error=${STALE_IF_ERROR_CACHE_DURATION}`
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -125,7 +125,7 @@ function loadDataForPageType(
|
|
|
125
125
|
.then((result) => {
|
|
126
126
|
if (result && result.data) {
|
|
127
127
|
if (result.data[ABORT_HANDLER] || (result.data.error && result.data.error.message)) {
|
|
128
|
-
return null
|
|
128
|
+
return null
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
return result;
|
|
@@ -485,12 +485,6 @@ exports.handleIsomorphicRoute = function handleIsomorphicRoute(
|
|
|
485
485
|
});
|
|
486
486
|
return res.redirect(301, result.data.location);
|
|
487
487
|
}
|
|
488
|
-
|
|
489
|
-
// For server errors (>=500),send statuss
|
|
490
|
-
if (statusCode >= 500) {
|
|
491
|
-
return res.sendStatus(statusCode);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
488
|
const seoInstance = getSeoInstance(seo, config, result.pageType);
|
|
495
489
|
const seoTags = seoInstance && seoInstance.getMetaTags(config, result.pageType || match.pageType, result, { url });
|
|
496
490
|
|
|
@@ -48,7 +48,8 @@ function getClientStub(hostname) {
|
|
|
48
48
|
page: {
|
|
49
49
|
id: 103,
|
|
50
50
|
title: "Testing",
|
|
51
|
-
content:
|
|
51
|
+
content:
|
|
52
|
+
"<html><head><title>Test</title></head><body><h1>Heading</h1></body></html>",
|
|
52
53
|
metadata: { header: true, footer: false },
|
|
53
54
|
type: "static-page",
|
|
54
55
|
"status-code": 200,
|
|
@@ -59,7 +60,8 @@ function getClientStub(hostname) {
|
|
|
59
60
|
page: {
|
|
60
61
|
id: 104,
|
|
61
62
|
title: "Testing",
|
|
62
|
-
content:
|
|
63
|
+
content:
|
|
64
|
+
"<html><head><title>Test</title></head><body><h1>Heading</h1></body></html>",
|
|
63
65
|
metadata: { header: false, footer: false },
|
|
64
66
|
type: "static-page",
|
|
65
67
|
"status-code": 200,
|
|
@@ -70,7 +72,8 @@ function getClientStub(hostname) {
|
|
|
70
72
|
page: {
|
|
71
73
|
id: 105,
|
|
72
74
|
title: "Testing mime type",
|
|
73
|
-
content:
|
|
75
|
+
content:
|
|
76
|
+
"<html><head><title>Test</title></head><body><h1>Heading</h1></body></html>",
|
|
74
77
|
metadata: {
|
|
75
78
|
header: false,
|
|
76
79
|
footer: false,
|
|
@@ -101,7 +104,9 @@ function createApp(loadData, routes, opts = {}) {
|
|
|
101
104
|
generateRoutes: () => routes,
|
|
102
105
|
loadData,
|
|
103
106
|
renderLayout: (res, { contentTemplate, store }) =>
|
|
104
|
-
res.send(
|
|
107
|
+
res.send(
|
|
108
|
+
JSON.stringify({ contentTemplate, store: store.getState() })
|
|
109
|
+
),
|
|
105
110
|
handleNotFound: false,
|
|
106
111
|
publisherConfig: {},
|
|
107
112
|
},
|
|
@@ -121,7 +126,10 @@ describe("Custom Route Handler", function () {
|
|
|
121
126
|
supertest(app)
|
|
122
127
|
.get("/moved-permanently")
|
|
123
128
|
.expect("Location", "/permanent-location")
|
|
124
|
-
.expect(
|
|
129
|
+
.expect(
|
|
130
|
+
"Cache-Control",
|
|
131
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
132
|
+
)
|
|
125
133
|
.expect("Vary", /Accept\-Encoding/)
|
|
126
134
|
.expect("Surrogate-Key", "sp/42/101")
|
|
127
135
|
.expect("Cache-Tag", "sp/42/101")
|
|
@@ -136,7 +144,10 @@ describe("Custom Route Handler", function () {
|
|
|
136
144
|
supertest(app)
|
|
137
145
|
.get("/moved-temporarily")
|
|
138
146
|
.expect("Location", "/temporary-location")
|
|
139
|
-
.expect(
|
|
147
|
+
.expect(
|
|
148
|
+
"Cache-Control",
|
|
149
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
150
|
+
)
|
|
140
151
|
.expect("Vary", /Accept\-Encoding/)
|
|
141
152
|
.expect("Surrogate-Key", "sp/42/102")
|
|
142
153
|
.expect("Cache-Tag", "sp/42/102")
|
|
@@ -152,7 +163,10 @@ describe("Custom Route Handler", function () {
|
|
|
152
163
|
supertest(app)
|
|
153
164
|
.get("/static-with-header-footer")
|
|
154
165
|
.expect("Content-Type", /html/)
|
|
155
|
-
.expect(
|
|
166
|
+
.expect(
|
|
167
|
+
"Cache-Control",
|
|
168
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
169
|
+
)
|
|
156
170
|
.expect("Vary", "Accept-Encoding")
|
|
157
171
|
.expect("Surrogate-Key", "sp/42/103")
|
|
158
172
|
.expect("Cache-Tag", "sp/42/103")
|
|
@@ -174,13 +188,19 @@ describe("Custom Route Handler", function () {
|
|
|
174
188
|
supertest(app)
|
|
175
189
|
.get("/static-without-header-footer")
|
|
176
190
|
.expect("Content-Type", /html/)
|
|
177
|
-
.expect(
|
|
191
|
+
.expect(
|
|
192
|
+
"Cache-Control",
|
|
193
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
194
|
+
)
|
|
178
195
|
.expect("Vary", "Accept-Encoding")
|
|
179
196
|
.expect("Surrogate-Key", "sp/42/104")
|
|
180
197
|
.expect("Cache-Tag", "sp/42/104")
|
|
181
198
|
.expect(200)
|
|
182
199
|
.then((res) => {
|
|
183
|
-
assert.equal(
|
|
200
|
+
assert.equal(
|
|
201
|
+
"<html><head><title>Test</title></head><body><h1>Heading</h1></body></html>",
|
|
202
|
+
res.text
|
|
203
|
+
);
|
|
184
204
|
})
|
|
185
205
|
.then(done);
|
|
186
206
|
});
|
|
@@ -213,7 +233,9 @@ describe("Custom Route Handler", function () {
|
|
|
213
233
|
it("Store reads config and data from data-loader response", function (done) {
|
|
214
234
|
const app = createApp(
|
|
215
235
|
(pageType, params, config, client, { host, next }) =>
|
|
216
|
-
pageType === "custom-static-page"
|
|
236
|
+
pageType === "custom-static-page"
|
|
237
|
+
? Promise.resolve({ data: { navigationMenu: [] }, config: {} })
|
|
238
|
+
: next(),
|
|
217
239
|
[{ pageType: "story-page", path: "/*" }]
|
|
218
240
|
);
|
|
219
241
|
supertest(app)
|
|
@@ -236,7 +258,10 @@ describe("Custom Route Handler", function () {
|
|
|
236
258
|
supertest(app)
|
|
237
259
|
.get("/moved-absolute")
|
|
238
260
|
.expect("Location", "https://www.google.com")
|
|
239
|
-
.expect(
|
|
261
|
+
.expect(
|
|
262
|
+
"Cache-Control",
|
|
263
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
264
|
+
)
|
|
240
265
|
.expect("Vary", /Accept\-Encoding/)
|
|
241
266
|
.expect("Surrogate-Key", "sp/42/105")
|
|
242
267
|
.expect("Cache-Tag", "sp/42/105")
|
|
@@ -250,7 +275,10 @@ describe("Custom Route Handler", function () {
|
|
|
250
275
|
);
|
|
251
276
|
supertest(app)
|
|
252
277
|
.get("/static-with-mime-type")
|
|
253
|
-
.expect(
|
|
278
|
+
.expect(
|
|
279
|
+
"Cache-Control",
|
|
280
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
281
|
+
)
|
|
254
282
|
.expect("Vary", /Accept\-Encoding/)
|
|
255
283
|
.expect("Surrogate-Key", "sp/42/105")
|
|
256
284
|
.expect("Cache-Tag", "sp/42/105")
|
|
@@ -265,7 +293,10 @@ describe("Custom Route Handler", function () {
|
|
|
265
293
|
);
|
|
266
294
|
supertest(app)
|
|
267
295
|
.get("/static-without-header-footer")
|
|
268
|
-
.expect(
|
|
296
|
+
.expect(
|
|
297
|
+
"Cache-Control",
|
|
298
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
299
|
+
)
|
|
269
300
|
.expect("Vary", "Accept-Encoding")
|
|
270
301
|
.expect("Surrogate-Key", "sp/42/104")
|
|
271
302
|
.expect("Cache-Tag", "sp/42/104")
|
|
@@ -168,7 +168,17 @@ describe("Isomorphic Handler", function () {
|
|
|
168
168
|
}),
|
|
169
169
|
}
|
|
170
170
|
);
|
|
171
|
-
|
|
171
|
+
|
|
172
|
+
supertest(app)
|
|
173
|
+
.get("/")
|
|
174
|
+
.expect("Content-Type", /html/)
|
|
175
|
+
.expect(500)
|
|
176
|
+
.then((res) => {
|
|
177
|
+
const response = JSON.parse(res.text);
|
|
178
|
+
assert.equal('<div data-page-type="not-found">foobar</div>', response.content);
|
|
179
|
+
assert.equal(true, response.store.qt.disableIsomorphicComponent);
|
|
180
|
+
})
|
|
181
|
+
.then(done, done);
|
|
172
182
|
});
|
|
173
183
|
|
|
174
184
|
it("Throws a 500 if loadData and loadErrorData both crash", function (done) {
|
|
@@ -184,7 +194,7 @@ describe("Isomorphic Handler", function () {
|
|
|
184
194
|
}
|
|
185
195
|
);
|
|
186
196
|
|
|
187
|
-
supertest(app).get("/").expect(500, done);
|
|
197
|
+
supertest(app).get("/").expect("Content-Type", /html/).expect(500, done);
|
|
188
198
|
});
|
|
189
199
|
|
|
190
200
|
it("Cache headers are set", function (done) {
|
|
@@ -200,7 +210,7 @@ describe("Isomorphic Handler", function () {
|
|
|
200
210
|
supertest(app)
|
|
201
211
|
.get("/")
|
|
202
212
|
.expect("Content-Type", /html/)
|
|
203
|
-
.expect("Cache-Control", "public,max-age=15,s-maxage=
|
|
213
|
+
.expect("Cache-Control", "public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400")
|
|
204
214
|
.expect("Vary", "Accept-Encoding")
|
|
205
215
|
.expect("Surrogate-Key", "foo bar")
|
|
206
216
|
.expect("Cache-Tag", "foo,bar")
|
|
@@ -503,7 +513,7 @@ describe("Isomorphic Handler", function () {
|
|
|
503
513
|
.then((res) => {
|
|
504
514
|
const cacheControl = res.header["cache-control"];
|
|
505
515
|
const cacheTag = res.header["cache-tag"];
|
|
506
|
-
assert.equal(cacheControl, "public,max-age=15,s-maxage=
|
|
516
|
+
assert.equal(cacheControl, "public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400");
|
|
507
517
|
assert.equal(cacheTag, "c/1/abcdefgh");
|
|
508
518
|
})
|
|
509
519
|
.then(done);
|
|
@@ -631,7 +641,7 @@ describe("Isomorphic Handler", function () {
|
|
|
631
641
|
const cacheControl = res.header["cache-control"];
|
|
632
642
|
const edgeCacheTag = res.header["edge-cache-tag"];
|
|
633
643
|
const contentSecurityPolicy = res.header["content-security-policy"];
|
|
634
|
-
assert.equal(cacheControl, "public,max-age=15,s-maxage=
|
|
644
|
+
assert.equal(cacheControl, "public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400");
|
|
635
645
|
assert.equal(edgeCacheTag, "c/1/abcdefgh");
|
|
636
646
|
assert.equal(
|
|
637
647
|
contentSecurityPolicy,
|
|
@@ -670,7 +680,7 @@ describe("Isomorphic Handler", function () {
|
|
|
670
680
|
const cacheControl = res.header["cache-control"];
|
|
671
681
|
const edgeCacheTag = res.header["edge-cache-tag"];
|
|
672
682
|
const contentSecurityPolicy = res.header["content-security-policy"];
|
|
673
|
-
assert.equal(cacheControl, "public,max-age=15,s-maxage=
|
|
683
|
+
assert.equal(cacheControl, "public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400");
|
|
674
684
|
assert.equal(edgeCacheTag, "c/1/abcdefgh");
|
|
675
685
|
assert.equal(
|
|
676
686
|
contentSecurityPolicy,
|
|
@@ -706,7 +716,10 @@ describe("Isomorphic Handler", function () {
|
|
|
706
716
|
.expect(200)
|
|
707
717
|
.then((res) => {
|
|
708
718
|
const cacheControl = res.header["cache-control"];
|
|
709
|
-
assert.equal(
|
|
719
|
+
assert.equal(
|
|
720
|
+
cacheControl,
|
|
721
|
+
"public,max-age=15,s-maxage=1800,stale-while-revalidate=1000,stale-if-error=14400"
|
|
722
|
+
);
|
|
710
723
|
})
|
|
711
724
|
.then(done);
|
|
712
725
|
});
|
|
@@ -727,7 +740,7 @@ describe("Isomorphic Handler", function () {
|
|
|
727
740
|
.expect(200)
|
|
728
741
|
.then((res) => {
|
|
729
742
|
const cacheControl = res.header["cache-control"];
|
|
730
|
-
assert.equal(cacheControl, "public,max-age=15,s-maxage=
|
|
743
|
+
assert.equal(cacheControl, "public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400");
|
|
731
744
|
})
|
|
732
745
|
.then(done);
|
|
733
746
|
});
|
|
@@ -508,7 +508,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
508
508
|
redirectUrls,
|
|
509
509
|
}
|
|
510
510
|
);
|
|
511
|
-
supertest(app)
|
|
511
|
+
supertest(app)
|
|
512
|
+
.get("/moved-permanently-1")
|
|
513
|
+
.expect("Location", "/permanent-location-1")
|
|
514
|
+
.expect(301, done);
|
|
512
515
|
});
|
|
513
516
|
|
|
514
517
|
it("Redirects all the urls with status code to 302 if redirectUrls is present", function (done) {
|
|
@@ -525,7 +528,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
525
528
|
],
|
|
526
529
|
}
|
|
527
530
|
);
|
|
528
|
-
supertest(app)
|
|
531
|
+
supertest(app)
|
|
532
|
+
.get("/moved-temporarily-1")
|
|
533
|
+
.expect("Location", "/temporarily-location-1")
|
|
534
|
+
.expect(302, done);
|
|
529
535
|
});
|
|
530
536
|
|
|
531
537
|
it("Renders homepage when redirect urls are present", function (done) {
|
|
@@ -549,7 +555,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
549
555
|
.expect(200)
|
|
550
556
|
.then((res) => {
|
|
551
557
|
const response = JSON.parse(res.text);
|
|
552
|
-
assert.equal(
|
|
558
|
+
assert.equal(
|
|
559
|
+
'<div data-page-type="home-page">foobar</div>',
|
|
560
|
+
response.content
|
|
561
|
+
);
|
|
553
562
|
assert.equal("foobar", response.store.qt.data.text);
|
|
554
563
|
assert.equal("127.0.0.1", response.store.qt.data.host);
|
|
555
564
|
assert.equal("home-page", response.store.qt.pageType);
|
|
@@ -563,7 +572,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
563
572
|
[{ pageType: "story-page", path: "/*" }],
|
|
564
573
|
{ redirectUrls: getRedirectUrl }
|
|
565
574
|
);
|
|
566
|
-
supertest(app)
|
|
575
|
+
supertest(app)
|
|
576
|
+
.get("/moved-permanently-1")
|
|
577
|
+
.expect("Location", "/permanent-location-1")
|
|
578
|
+
.expect(301, done);
|
|
567
579
|
});
|
|
568
580
|
|
|
569
581
|
it("Should handle Route Parameters redirects properly", function (done) {
|
|
@@ -572,7 +584,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
572
584
|
[{ pageType: "story-page", path: "/*" }],
|
|
573
585
|
{ redirectUrls: getRedirectUrl }
|
|
574
586
|
);
|
|
575
|
-
supertest(app)
|
|
587
|
+
supertest(app)
|
|
588
|
+
.get("/india/news/some-slug")
|
|
589
|
+
.expect("Location", "/india/some-slug")
|
|
590
|
+
.expect(301, done);
|
|
576
591
|
});
|
|
577
592
|
|
|
578
593
|
it("Should handle multiple Route Parameters redirects properly", function (done) {
|
|
@@ -581,7 +596,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
581
596
|
[{ pageType: "story-page", path: "/*" }],
|
|
582
597
|
{ redirectUrls: getRedirectUrl }
|
|
583
598
|
);
|
|
584
|
-
supertest(app)
|
|
599
|
+
supertest(app)
|
|
600
|
+
.get("/india/foo/some-slug/slug")
|
|
601
|
+
.expect("Location", "/india/some-slug")
|
|
602
|
+
.expect(302, done);
|
|
585
603
|
});
|
|
586
604
|
|
|
587
605
|
it("Should handle interchanging route parameter redirects properly", function (done) {
|
|
@@ -590,7 +608,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
590
608
|
[{ pageType: "story-page", path: "/*" }],
|
|
591
609
|
{ redirectUrls: getRedirectUrl }
|
|
592
610
|
);
|
|
593
|
-
supertest(app)
|
|
611
|
+
supertest(app)
|
|
612
|
+
.get("/foo/something/bar")
|
|
613
|
+
.expect("Location", "/bar/something/foo")
|
|
614
|
+
.expect(301, done);
|
|
594
615
|
});
|
|
595
616
|
|
|
596
617
|
it("Should handle external redirects", function (done) {
|
|
@@ -599,7 +620,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
599
620
|
[{ pageType: "story-page", path: "/*" }],
|
|
600
621
|
{ redirectUrls: getRedirectUrl }
|
|
601
622
|
);
|
|
602
|
-
supertest(app)
|
|
623
|
+
supertest(app)
|
|
624
|
+
.get("/something/new")
|
|
625
|
+
.expect("Location", "https://www.google.com/something")
|
|
626
|
+
.expect(301, done);
|
|
603
627
|
});
|
|
604
628
|
|
|
605
629
|
it("Should handle external redirects with params", function (done) {
|
|
@@ -608,7 +632,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
608
632
|
[{ pageType: "story-page", path: "/*" }],
|
|
609
633
|
{ redirectUrls: getRedirectUrl }
|
|
610
634
|
);
|
|
611
|
-
supertest(app)
|
|
635
|
+
supertest(app)
|
|
636
|
+
.get("/something/new1")
|
|
637
|
+
.expect("Location", "https://www.google.com/new1")
|
|
638
|
+
.expect(301, done);
|
|
612
639
|
});
|
|
613
640
|
|
|
614
641
|
it("Should not crash if redirectUrls is not present", function (done) {
|
|
@@ -619,7 +646,10 @@ describe("Redirect Routes Handler", function () {
|
|
|
619
646
|
supertest(app)
|
|
620
647
|
.get("/moved-temporarily-1")
|
|
621
648
|
.expect("Location", "/temporarily-location-1")
|
|
622
|
-
.expect(
|
|
649
|
+
.expect(
|
|
650
|
+
"Cache-Control",
|
|
651
|
+
"public,max-age=15,s-maxage=900,stale-while-revalidate=1000,stale-if-error=14400"
|
|
652
|
+
)
|
|
623
653
|
.expect("Vary", /Accept\-Encoding/)
|
|
624
654
|
.expect("Surrogate-Key", "sp/42/102")
|
|
625
655
|
.expect("Cache-Tag", "sp/42/102")
|