FIX: Ember CLI was losing some preloaded data (#13406)

The `bootstrap.json` contains most preloaded information but some routes
provide extra information, such as invites.

This fixes the issue by having the preload request pass on the preloaded
data from the source page, which is then merged with the bootstrap's
preloaded data for the final HTML payload.
This commit is contained in:
Robin Ward 2021-06-16 13:45:02 -04:00 committed by GitHub
parent 20dbcbf022
commit 651b8a23b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 11 deletions

View File

@ -132,10 +132,10 @@ function preloaded(buffer, bootstrap) {
const BUILDERS = {
"html-tag": htmlTag,
"before-script-load": beforeScriptLoad,
head: head,
body: body,
head,
body,
"hidden-login-form": hiddenLoginForm,
preloaded: preloaded,
preloaded,
"body-footer": bodyFooter,
"locale-script": localeScript,
};
@ -148,14 +148,20 @@ function replaceIn(bootstrap, template, id, headers) {
return template.replace(`<bootstrap-content key="${id}">`, contents);
}
function applyBootstrap(bootstrap, template, headers) {
async function applyBootstrap(bootstrap, template, response) {
// If our initial page added some preload data let's not lose that.
let json = await response.json();
if (json && json.preloaded) {
bootstrap.preloaded = Object.assign(json.preloaded, bootstrap.preloaded);
}
Object.keys(BUILDERS).forEach((id) => {
template = replaceIn(bootstrap, template, id, headers);
template = replaceIn(bootstrap, template, id, response);
});
return template;
}
function buildFromBootstrap(assetPath, proxy, baseURL, req, headers) {
function buildFromBootstrap(assetPath, proxy, baseURL, req, response) {
// eslint-disable-next-line
return new Promise((resolve, reject) => {
fs.readFile(
@ -170,8 +176,9 @@ function buildFromBootstrap(assetPath, proxy, baseURL, req, headers) {
getJSON(url, null, req.headers)
.then((json) => {
resolve(applyBootstrap(json.bootstrap, template, headers));
return applyBootstrap(json.bootstrap, template, response);
})
.then(resolve)
.catch((e) => {
reject(
`Could not get ${proxy}${baseURL}bootstrap.json\n\n${e.toString()}`
@ -203,16 +210,17 @@ async function handleRequest(assetPath, proxy, baseURL, req, res) {
let get = bent("GET", [200, 301, 302, 303, 307, 308, 404, 403, 500]);
let response = await get(url, null, req.headers);
res.set(response.headers);
res.set("content-type", "text/html");
if (response.headers["x-discourse-bootstrap-required"] === "true") {
req.headers["X-Discourse-Asset-Path"] = req.path;
let json = await buildFromBootstrap(
let html = await buildFromBootstrap(
assetPath,
proxy,
baseURL,
req,
response.headers
response
);
return res.send(json);
return res.send(html);
}
res.status(response.status);
res.send(await response.text());

View File

@ -322,7 +322,9 @@ class ApplicationController < ActionController::Base
end
def send_ember_cli_bootstrap
head 200, content_type: "text/html", "X-Discourse-Bootstrap-Required": true
response.headers['X-Discourse-Bootstrap-Required'] = true
response.headers['Content-Type'] = "application/json"
render json: { preloaded: @preloaded }
end
# If a controller requires a plugin, it will raise an exception if that plugin is