Skip to content

Commit

Permalink
Merge pull request #830 from openSUSE/devserver_manifests
Browse files Browse the repository at this point in the history
Development server - handle also the manifests.js file request
  • Loading branch information
lslezak authored Oct 31, 2023
2 parents f115eb4 + a774481 commit 655e957
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 4 deletions.
5 changes: 3 additions & 2 deletions web/src/DevServerWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ export default function DevServerWrapper({ children }) {
// handle updating the iframe with the login form
const onFrameLoad = () => {
const passwordInput = iframeRef.current.contentWindow.document.getElementById(loginId);
// if there is no password field displayed then the user has authenticated successfully
if (!passwordInput) setIsAuthenticated(true);
// reload the window so the manifests.js file referenced from the
// index.html file is also loaded again
if (!passwordInput) window.location.reload();
};

return <iframe ref={iframeRef} onLoad={onFrameLoad} src={loginPath} className="full-size" />;
Expand Down
48 changes: 48 additions & 0 deletions web/src/lib/webpack-manifests-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const fs = require("fs");
const path = require("path");

const manifestFile = path.join(__dirname, "..", "manifest.json");

// this function is injected as a string into the resulting JS file
const updateAgamaManifest = (data) => {
if (typeof cockpit === "object" && cockpit.manifests) {
cockpit.manifests.agama = data;
}
};

// This function processes the webpack HTTP proxy request for manifests.js file.
//
// Patching the original JS code is difficult so rather inject code
// which rewrites the Agama manifest data with new content.
//
// @see https://github.com/http-party/node-http-proxy#modify-response
//
// @param proxyRes HTTP proxy resource
// @param req HTTP request
// @param res HTTP response
module.exports = function (proxyRes, req, res) {
// collect parts of the original response
const body = [];

proxyRes.on("data", function (chunk) {
body.push(chunk);
});

proxyRes.on("end", function () {
// forward the original status code
res.statusCode = proxyRes.statusCode;

// patch the response only on success otherwise there
// might be some unexpected content (HTML error page)
if (proxyRes.statusCode === 200 && fs.existsSync(manifestFile)) {
const manifest = fs.readFileSync(manifestFile);
// use an immediately-invoked function expression to inject the new
// manifest content
res.end(Buffer.concat(body).toString() + "((" +
updateAgamaManifest.toString() + ")(" + manifest + "));");
} else {
// otherwise just return the original content
res.end(Buffer.concat(body).toString());
}
});
};
15 changes: 13 additions & 2 deletions web/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const webpack = require('webpack');
const po_handler = require("./src/lib/webpack-po-handler");
const manifests_handler = require("./src/lib/webpack-manifests-handler");

/* A standard nodejs and webpack pattern */
const production = process.env.NODE_ENV === 'production';
Expand Down Expand Up @@ -100,15 +101,25 @@ module.exports = {
externals: { cockpit: "cockpit" },
devServer: {
hot: true,
// forward all cockpit connections to a real Cockpit instance
proxy: {
// forward all cockpit connections to a real Cockpit instance
"/cockpit": {
target: cockpitTarget,
// redirect also the websocket connections
ws: true,
// ignore SSL problems (self-signed certificate)
secure: false,
},
// forward the manifests.js request and patch the response with the
// current Agama manifest from the ./src/manifest.json file
"/manifests.js": {
target: cockpitTarget + "/cockpit/@localhost/",
// ignore SSL problems (self-signed certificate)
secure: false,
// the response is modified by the onProxyRes handler
selfHandleResponse : true,
onProxyRes: manifests_handler,
},
},
// use https so Cockpit uses wss:// when connecting to the backend
server: "https",
Expand All @@ -118,7 +129,7 @@ module.exports = {

// Cockpit handles the "po.js" requests specially
setupMiddlewares: (middlewares, devServer) => {
devServer.app.get("/po.js", (req, res) => po_handler(req, res));
devServer.app.get("/po.js", po_handler);
return middlewares;
}
},
Expand Down

0 comments on commit 655e957

Please sign in to comment.