From 651b8a23b8c619cf23468ca38b9fed63d597d9c3 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 16 Jun 2021 13:45:02 -0400 Subject: [PATCH] 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. --- .../discourse/lib/bootstrap-json/index.js | 28 ++++++++++++------- app/controllers/application_controller.rb | 4 ++- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js index f8dc77a277d..7c78d2d1f50 100644 --- a/app/assets/javascripts/discourse/lib/bootstrap-json/index.js +++ b/app/assets/javascripts/discourse/lib/bootstrap-json/index.js @@ -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(``, 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()); diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5d16eb256cb..7ec30918698 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -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