From 1465a91d2ebc501d52da9782ed0a978efc86a7ca Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Wed, 4 Dec 2024 15:15:23 +0000 Subject: [PATCH 01/13] also include the hassio rest api app when serving locally --- script/develop_and_serve | 12 ++++++++---- script/serve.js | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 script/serve.js diff --git a/script/develop_and_serve b/script/develop_and_serve index 529fbc6b2578..3db390976399 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -60,11 +60,15 @@ else fi echo Core is used from ${coreUrl} +if [ ! -d "./hassio/build" ]; then + echo Building hassio + # the hassio rest app doesn't need the HASS_URL override, + # it will use the url from the current login session + hassio/script/build_hassio +fi + # build the frontend so it connects to the passed core HASS_URL="$coreUrl" ./script/develop & # serve the frontend -yarn dlx serve -l $frontendPort ./hass_frontend -s & - -# keep the script running while serving -wait +yarn exec node ./script/serve.js $frontendPort \ No newline at end of file diff --git a/script/serve.js b/script/serve.js new file mode 100644 index 000000000000..b58a18fcf695 --- /dev/null +++ b/script/serve.js @@ -0,0 +1,17 @@ +import express from "express"; +import path from "path"; +import { fileURLToPath } from "url"; + +const port = parseInt(process.argv[2] ?? "8123"); +const repoDir = path.join(fileURLToPath(import.meta.url), "../.."); + +const app = express(); +app.use("/", express.static(path.join(repoDir, "hass_frontend"))); +app.use("/api/hassio/app", express.static(path.join(repoDir, "hassio/build"))); +app.get("*", (req, res) => { + res.sendFile(path.join(repoDir, "hass_frontend/index.html")); +}); + +app.listen(port, () => { + console.log(`Running at http://localhost:${port}`); +}); From a5da4a062b58af654fc5edccec0ed537180a3c19 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Wed, 4 Dec 2024 15:42:36 +0000 Subject: [PATCH 02/13] forward locally made api calls to the backend --- script/develop_and_serve | 2 +- script/serve.js | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/script/develop_and_serve b/script/develop_and_serve index 3db390976399..db80b1653244 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -71,4 +71,4 @@ fi HASS_URL="$coreUrl" ./script/develop & # serve the frontend -yarn exec node ./script/serve.js $frontendPort \ No newline at end of file +yarn exec node ./script/serve.js "$coreUrl" $frontendPort \ No newline at end of file diff --git a/script/serve.js b/script/serve.js index b58a18fcf695..038f6e2e8323 100644 --- a/script/serve.js +++ b/script/serve.js @@ -2,16 +2,33 @@ import express from "express"; import path from "path"; import { fileURLToPath } from "url"; -const port = parseInt(process.argv[2] ?? "8123"); +const coreUrl = process.argv[2]; +const port = parseInt(process.argv[3] ?? "8123"); + const repoDir = path.join(fileURLToPath(import.meta.url), "../.."); +import { createProxyMiddleware } from "http-proxy-middleware"; + +const coreProxy = createProxyMiddleware({ + target: coreUrl, + changeOrigin: true, +}); + const app = express(); app.use("/", express.static(path.join(repoDir, "hass_frontend"))); app.use("/api/hassio/app", express.static(path.join(repoDir, "hassio/build"))); +app.use("/api", coreProxy); app.get("*", (req, res) => { res.sendFile(path.join(repoDir, "hass_frontend/index.html")); }); -app.listen(port, () => { - console.log(`Running at http://localhost:${port}`); +var server = app.listen(port, () => { + console.log( + `Running at http://localhost:${port}, connected to core on ${coreUrl}` + ); +}); + +process.on("SIGINT", function () { + console.log("Shutting down file server"); + server.close(); }); From 1ee84f14def51a1c3c899e34b915109e4cead928 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Wed, 4 Dec 2024 17:00:12 +0000 Subject: [PATCH 03/13] fixed difference in meaning of localhost when using devcontainer to develop frontend using the serve option --- .devcontainer/devcontainer.json | 3 ++- script/develop_and_serve | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7f8ab1df13e7..78483aa6dfce 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,8 @@ "name": "Home Assistant Frontend", "build": { "dockerfile": "Dockerfile", - "context": ".." + "context": "..", + "options": [ "--add-host=host.docker.internal:host-gateway" ] }, "appPort": "8124:8123", "postCreateCommand": "sudo apt update && sudo apt upgrade -y && sudo apt install -y libpcap-dev", diff --git a/script/develop_and_serve b/script/develop_and_serve index db80b1653244..9d8e93650317 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # # This script can be used to develop and test the frontend without having to # link the build in a running core instance through the frontend/development_repo setting. @@ -70,5 +70,9 @@ fi # build the frontend so it connects to the passed core HASS_URL="$coreUrl" ./script/develop & -# serve the frontend -yarn exec node ./script/serve.js "$coreUrl" $frontendPort \ No newline at end of file +if [ -n "$DEVCONTAINER" ]; then + nodeCoreUrl="${coreUrl/localhost/host.docker.internal}" +else + nodeCoreUrl="$coreUrl" +fi +yarn exec node ./script/serve.js "$nodeCoreUrl" $frontendPort \ No newline at end of file From b6ca770f38e5e4a1563a02505b86a6c3dbe31811 Mon Sep 17 00:00:00 2001 From: Petar Petrov Date: Thu, 5 Dec 2024 08:45:44 +0200 Subject: [PATCH 04/13] lint fix --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 78483aa6dfce..5f72fca269c1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ "build": { "dockerfile": "Dockerfile", "context": "..", - "options": [ "--add-host=host.docker.internal:host-gateway" ] + "options": ["--add-host=host.docker.internal:host-gateway"] }, "appPort": "8124:8123", "postCreateCommand": "sudo apt update && sudo apt upgrade -y && sudo apt install -y libpcap-dev", From 39b7fcbe94a6b738b22427d49f1108f88b624462 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 13:46:35 +0000 Subject: [PATCH 05/13] fixed problem with ingress add-ons, tested using Advanced SSH & Web Terminal --- script/develop_and_serve | 11 ----------- script/serve.js | 38 +++++++++++++++++++++++++++++++++----- script/serve.pfx | Bin 0 -> 2651 bytes 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100755 script/serve.pfx diff --git a/script/develop_and_serve b/script/develop_and_serve index 9d8e93650317..60837ae2c4e3 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -49,17 +49,6 @@ do esac done -# display used settings -if [ -n "$DEVCONTAINER" ]; then - echo Frontend is available inside container as http://localhost:${frontendPort} - if [ 8123 -eq $frontendPort ]; then - echo Frontend is available on container host as http://localhost:8124 - fi -else - echo Frontend is hosted on http://localhost:${frontendPort} -fi -echo Core is used from ${coreUrl} - if [ ! -d "./hassio/build" ]; then echo Building hassio # the hassio rest app doesn't need the HASS_URL override, diff --git a/script/serve.js b/script/serve.js index 038f6e2e8323..ef9c6097cca1 100644 --- a/script/serve.js +++ b/script/serve.js @@ -1,4 +1,6 @@ import express from "express"; +import https from "https"; +import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; @@ -12,6 +14,7 @@ import { createProxyMiddleware } from "http-proxy-middleware"; const coreProxy = createProxyMiddleware({ target: coreUrl, changeOrigin: true, + ws: true, }); const app = express(); @@ -22,13 +25,38 @@ app.get("*", (req, res) => { res.sendFile(path.join(repoDir, "hass_frontend/index.html")); }); -var server = app.listen(port, () => { - console.log( - `Running at http://localhost:${port}, connected to core on ${coreUrl}` - ); +// if the core uses https, also use https for serving to avoid problems +// with headers like Strict-Transport-Security +const useHttps = coreUrl.startsWith("https:"); + +const appServer = useHttps + ? https.createServer( + { + pfx: fs.readFileSync(repoDir + "/script/serve.pfx"), + passphrase: "localhost", + }, + app + ) + : app; + +const frontendBase = `http${useHttps ? "s" : ""}://localhost`; +appServer.listen(port, () => { + if (process.env.DEVCONTAINER !== undefined) { + console.log( + `Frontend is available inside container as ${frontendBase}:${port}` + ); + if (port === 8123) { + console.log( + `Frontend is available on container host as ${frontendBase}://localhost:8124` + ); + } + } else { + console.log(`Frontend is hosted on ${frontendBase}:${port}`); + } + console.log(`Core is used from ${coreUrl}`); }); process.on("SIGINT", function () { console.log("Shutting down file server"); - server.close(); + process.exit(0); }); diff --git a/script/serve.pfx b/script/serve.pfx new file mode 100755 index 0000000000000000000000000000000000000000..a33ea464f44a6651fb13d2535e2c94306479a94d GIT binary patch literal 2651 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 DALYcQ literal 0 HcmV?d00001 From 76d791c50f7744c0ec6a1be2a4d130dafa77ca7e Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 14:04:38 +0000 Subject: [PATCH 06/13] replace binary pfx with text based formats to prevent git from messing it up --- script/serve.crt | 19 +++++++++++++++++++ script/serve.js | 4 ++-- script/serve.key | 28 ++++++++++++++++++++++++++++ script/serve.pfx | Bin 2651 -> 0 bytes 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100755 script/serve.crt create mode 100755 script/serve.key delete mode 100755 script/serve.pfx diff --git a/script/serve.crt b/script/serve.crt new file mode 100755 index 000000000000..9466b90de748 --- /dev/null +++ b/script/serve.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIIfUe7tkwbkhEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UE +AxMJbG9jYWxob3N0MB4XDTIxMTIzMTA1NDgwMVoXDTIyMTIzMTA1NDgwMVowFDES +MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAxfND9r1VoBJON91dz2/60WfUJKSTkXEJItMU0ZvoIyWiH51DydFS8q2oM5zB +GQz92dRIaMQHz7TqHhRnZ/sOzqJ2ZOUGTWwzYt6I8Yq/sMimS421/ogsB5K3rYL0 +EvMfb33Wejt30krD6AtWf/a+Mz8GpmC1a+BE6nti7o0frvK5xNwTnOi/utY72tN1 +1rcVLFMVzJBf6o9X8cGEEAsyMiBr7HPAyRkP2k3PQE0icVuMSEc63KLzqYp9tLKO +6zgQNs1W2WbMxQ3CgEio3f5PMld56aMomUcxJ0Tn12n4YvyvwOu6DZVX3xHVvXHH +FyBny4OjKF31pl9HWqlzrRTM8QIDAQABo2IwYDAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIFoDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATAXBgNVHREBAf8EDTAL +gglsb2NhbGhvc3QwDwYKKwYBBAGCN1QBAQQBAjANBgkqhkiG9w0BAQsFAAOCAQEA +MnIxAm0k70OfJWMCN9FdiJW2zAScvmv/DywqPoJqTrEelnszrROK2XynS536JeXg +lbIhZRfKTA3IABgGdoG/6soQYfMGFAwaRKmXh+KchThLrtuck+tX30KHJFHxD4cX +Jf2sqSSz5ol3X+W0CgWxPUOklPX3MDrAJ++U43njokZd6Q3eqes+HQl1XRM8Jsla +xPXTsG++48aJl6l0Lz6hqTSA9z7H6ddC3NWWHz9vrpGem/oaMXfdftnD8VultQX4 +al/iGwwLMMinGAOYmYF8qCWbcj1YNkqI7Iiu8ZQCOLMwr3HDA9SAvLLprw18dWSy +K73E/ijgqgJ70XV3MNGlCw== +-----END CERTIFICATE----- diff --git a/script/serve.js b/script/serve.js index ef9c6097cca1..07adaec878b0 100644 --- a/script/serve.js +++ b/script/serve.js @@ -32,8 +32,8 @@ const useHttps = coreUrl.startsWith("https:"); const appServer = useHttps ? https.createServer( { - pfx: fs.readFileSync(repoDir + "/script/serve.pfx"), - passphrase: "localhost", + key: fs.readFileSync(repoDir + "/script/serve.key"), + cert: fs.readFileSync(repoDir + "/script/serve.crt"), }, app ) diff --git a/script/serve.key b/script/serve.key new file mode 100755 index 000000000000..4fc46bbbab03 --- /dev/null +++ b/script/serve.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDF80P2vVWgEk43 +3V3Pb/rRZ9QkpJORcQki0xTRm+gjJaIfnUPJ0VLyragznMEZDP3Z1EhoxAfPtOoe +FGdn+w7OonZk5QZNbDNi3ojxir+wyKZLjbX+iCwHkretgvQS8x9vfdZ6O3fSSsPo +C1Z/9r4zPwamYLVr4ETqe2LujR+u8rnE3BOc6L+61jva03XWtxUsUxXMkF/qj1fx +wYQQCzIyIGvsc8DJGQ/aTc9ATSJxW4xIRzrcovOpin20so7rOBA2zVbZZszFDcKA +SKjd/k8yV3npoyiZRzEnROfXafhi/K/A67oNlVffEdW9cccXIGfLg6MoXfWmX0da +qXOtFMzxAgMBAAECggEBAMKH97GCjaQ6eR3TcP6LiIzEIapFBjR3Rkgv8hSvx6jK +shGphlXOXVraKCNYmDdbGhk40lQK2bZYj38yBBEem4WcCQfMPq5VeAZgtWnSNeGw +viQfxsu13Lcwi0t8FwqMXMc/fkgvKujByta+Vap5vJ81//3/qiqygmeBDE9s5scQ +S4G6nBtnMxbw+nX/MpTRR/lpCI6oS3S22NzzkYuhMb24PGI2A7mDGXvIqe3TCzWJ +UYIznWvgBSE8VRmU/j3pSDsVPKh6YFYBiCy2Tnx4hr5gmuC/9oK8J53dPwsfa4aN +znwQ1pMTHnztMUZgYUYWU31g7Kf56lpZyadOtIDHf4UCgYEAyuUq/V61z3zp5ULd +QT0k5covLwX5h40Rbsc63BR1vtg6zpvnwDUgnA0pM6f5S5XgVN9+tr6jpTtB6URd +DFMouUInrun2GIwxqRNlgYHnxod4sxJ547gPK68skaXMjK6HHBKW/fNCZG1BXUxy +Hf9C3s0UdJ0Hztc9uu9FKEjTUfMCgYEA+cLELcEOwuuNW5H5FsK6JiapHVb10diu +3NtYaChov3xX0cPS5NblTTK2MAy1BzN7eYFFlQg8usrDsgYgMTaeUoGgBlCxU+n9 +yxqfOg/wF56F4NWlvYeMMPpLsjCu1wOSxJuduvRWb0XWgOTFfG4T0TviP+AAoaeX +uogEZu5w+osCgYBNCCkEPVslxbU/190NEdvaaqLzZX9RmZuOxZFxUUtLA+l/2+1n +KkSROuXzuMiLjAG594iydTrIVvE1UUFKlqAVhipu3GEU/NU17ilRvDJ1S6XlxxQE +AzOvUDjJq3s3xmOBowU0sZD5dAmnFIkXHn0S/iXQCHaYb1v+hy1omA2zRQKBgCaG +eXZJSjqc1PAkAxUUslwCKKHi8QYOc2KT3v4qBYZL6svrddNgpnwS73FX9HCI62nh +m9cSLzPs5OTH9x1APImjfwiaV9AGzuQOVjNBlBpAlIwKyIcEqoY/hX+V7NIztebn +zhuxZsfBMQYuw5ue6yWiJBMQPWiyDkByjKNH8ltjAoGAHbQPSyxpyfCWnQV9R1HQ +gsgVw/hrF8Lo+j8ULSGl3+jMqQbg65t16vw6tQInyUPm0frcCLBJZN948K66ysFB +8U2pgdI7kx51sOsIev0cb/0d5e6c/SXsPeQ1NYK6v+NeLfx5Rc74NASbuOfiYLQk +DzoK6WnUS6LVj6joil/0ckE= +-----END PRIVATE KEY----- diff --git a/script/serve.pfx b/script/serve.pfx deleted file mode 100755 index a33ea464f44a6651fb13d2535e2c94306479a94d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2651 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 DALYcQ From 7cf077fbacecf2365b7055f1c3fbb6241fd8646a Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 14:15:51 +0000 Subject: [PATCH 07/13] added more documentation --- script/develop_and_serve | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/develop_and_serve b/script/develop_and_serve index 60837ae2c4e3..95a89d25bcb2 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -2,6 +2,8 @@ # # This script can be used to develop and test the frontend without having to # link the build in a running core instance through the frontend/development_repo setting. +# Instead you only have to configure the cors_allowed_origins of the http element +# to grant access to whatever url you use to access your development frontend. # # WARNING: # If you have an active login session in the frontend. The core that was used @@ -19,6 +21,10 @@ # For example: script/develop_and_serve -c https://myhost.duckdns.org:8123 # This will also work for existing production core instances. # It does not need to be a development version hosted locally. +# However note that if the core you connect to uses https, you will also need to use +# https to connect to your local development frontend. A self signed certificate +# for localhost is included and will be used when necessary. You just have to accept +# it as valid when browsing to your local development frontend. # # You can change the port the frontend is served on by passing the -p option. # For example: script/develop_and_serve -p 8654 From f2e031cc16d3f6964050bb189902f9f0378c31f7 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 15:01:06 +0000 Subject: [PATCH 08/13] removed the need for using cors --- script/develop_and_serve | 5 +---- script/serve.js | 8 ++++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/script/develop_and_serve b/script/develop_and_serve index 95a89d25bcb2..ef0cd18a6707 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -2,8 +2,6 @@ # # This script can be used to develop and test the frontend without having to # link the build in a running core instance through the frontend/development_repo setting. -# Instead you only have to configure the cors_allowed_origins of the http element -# to grant access to whatever url you use to access your development frontend. # # WARNING: # If you have an active login session in the frontend. The core that was used @@ -62,8 +60,7 @@ if [ ! -d "./hassio/build" ]; then hassio/script/build_hassio fi -# build the frontend so it connects to the passed core -HASS_URL="$coreUrl" ./script/develop & +./script/develop & if [ -n "$DEVCONTAINER" ]; then nodeCoreUrl="${coreUrl/localhost/host.docker.internal}" diff --git a/script/serve.js b/script/serve.js index 07adaec878b0..ec1ced20e1f0 100644 --- a/script/serve.js +++ b/script/serve.js @@ -21,9 +21,17 @@ const app = express(); app.use("/", express.static(path.join(repoDir, "hass_frontend"))); app.use("/api/hassio/app", express.static(path.join(repoDir, "hassio/build"))); app.use("/api", coreProxy); +app.get("/auth/authorize", (req, res) => { + res.sendFile(path.join(repoDir, "hass_frontend/authorize.html")); +}); +app.use("/auth", coreProxy); +app.get("/onboarding", (req, res) => { + res.sendFile(path.join(repoDir, "hass_frontend/onboarding.html")); +}); app.get("*", (req, res) => { res.sendFile(path.join(repoDir, "hass_frontend/index.html")); }); +app.use("/", coreProxy); // if the core uses https, also use https for serving to avoid problems // with headers like Strict-Transport-Security From 500d655ba631bdbffc53885d8738cb949804fd2d Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 15:19:14 +0000 Subject: [PATCH 09/13] made it easier to serve an existing build without using develop_and_serve --- package.json | 1 + script/develop_and_serve | 21 +-------------------- script/serve.js | 13 ++++++++++--- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 522bd52a3b43..fde4ef552e9d 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "postinstall": "husky", "prepack": "pinst --disable", "postpack": "pinst --enable", + "serve": "node ./script/serve.js", "test": "vitest run --config test/vitest.config.ts", "test:coverage": "vitest run --config test/vitest.config.ts --coverage" }, diff --git a/script/develop_and_serve b/script/develop_and_serve index ef0cd18a6707..eab009eb8d02 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -34,25 +34,6 @@ set -e cd "$(dirname "$0")/.." -# parse input paramters -if [ -n "$DEVCONTAINER" ]; then - frontendPort=8123 -else - frontendPort=8124 -fi - -coreUrl=http://localhost:8123 - -while getopts p:c:h flag -do - case "${flag}" in - p) frontendPort=${OPTARG};; - c) coreUrl="${OPTARG}";; - h) echo Documentation can be found inside "$0" && exit 0;; - *) echo Documentation can be found inside "$0" && exit 1;; - esac -done - if [ ! -d "./hassio/build" ]; then echo Building hassio # the hassio rest app doesn't need the HASS_URL override, @@ -67,4 +48,4 @@ if [ -n "$DEVCONTAINER" ]; then else nodeCoreUrl="$coreUrl" fi -yarn exec node ./script/serve.js "$nodeCoreUrl" $frontendPort \ No newline at end of file +yarn serve "$@" \ No newline at end of file diff --git a/script/serve.js b/script/serve.js index ec1ced20e1f0..9ad5a77dfa33 100644 --- a/script/serve.js +++ b/script/serve.js @@ -1,11 +1,18 @@ import express from "express"; import https from "https"; import fs from "fs"; +import minimist from "minimist"; import path from "path"; import { fileURLToPath } from "url"; -const coreUrl = process.argv[2]; -const port = parseInt(process.argv[3] ?? "8123"); +const parsedArguments = { + c: "http://localhost:8123", + p: process.env.DEVCONTAINER !== undefined ? "8123" : "8124", + ...minimist(process.argv.slice(2)), +}; + +const coreUrl = parsedArguments.c; +const port = parseInt(parsedArguments.p); const repoDir = path.join(fileURLToPath(import.meta.url), "../.."); @@ -55,7 +62,7 @@ appServer.listen(port, () => { ); if (port === 8123) { console.log( - `Frontend is available on container host as ${frontendBase}://localhost:8124` + `Frontend is available on container host as ${frontendBase}:8124` ); } } else { From dc101a5f850a0ded4ea59c41c9183d6dfece8155 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Fri, 6 Dec 2024 15:45:59 +0000 Subject: [PATCH 10/13] moved remain functionality to serve script --- script/develop_and_serve | 5 ----- script/serve.js | 5 ++++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/script/develop_and_serve b/script/develop_and_serve index eab009eb8d02..0ac3866d4a19 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -43,9 +43,4 @@ fi ./script/develop & -if [ -n "$DEVCONTAINER" ]; then - nodeCoreUrl="${coreUrl/localhost/host.docker.internal}" -else - nodeCoreUrl="$coreUrl" -fi yarn serve "$@" \ No newline at end of file diff --git a/script/serve.js b/script/serve.js index 9ad5a77dfa33..842fe10295d2 100644 --- a/script/serve.js +++ b/script/serve.js @@ -11,7 +11,10 @@ const parsedArguments = { ...minimist(process.argv.slice(2)), }; -const coreUrl = parsedArguments.c; +const coreUrl = + process.env.DEVCONTAINER !== undefined + ? parsedArguments.c.replace("/localhost:", "/host.docker.internal:") + : parsedArguments.c; const port = parseInt(parsedArguments.p); const repoDir = path.join(fileURLToPath(import.meta.url), "../.."); From 751aca89a42f895eca7a27e4b6b8cc0d913c26c2 Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Sat, 7 Dec 2024 11:15:08 +0000 Subject: [PATCH 11/13] some more cleanup after changing the concept to proxy based --- script/develop_and_serve | 20 +++++------ script/serve.js | 71 +++++++++++++++++++++------------------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/script/develop_and_serve b/script/develop_and_serve index 0ac3866d4a19..1108f4891162 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -3,17 +3,11 @@ # This script can be used to develop and test the frontend without having to # link the build in a running core instance through the frontend/development_repo setting. # -# WARNING: -# If you have an active login session in the frontend. The core that was used -# as a backend during the time of the login remains used until you logout again. -# So if you reuse the url hosting the frontend, you will need to logout before -# it will actually start using the core backend configured by this script. -# -# If you run this script without parameters, the frontend will be accessible under http://localhost:8124. -# And it will use the core instance running under http://localhost:8123 as a backend. -# Note that from a devcontainer, the frontend will be accessible under port 8124 on the host container. -# Inside the devcontainer it will be accessible under port 8123 instead. -# The core instance endpoint remains the same in both cases, as this is resolved from the browser. +# If you run this script without parameters, the frontend will be accessible under +# http://localhost:8124. And it will use the core instance running under +# http://localhost:8123 as a backend. Note that if you're developing using a +# devcontainer, these are the url's on the host container +# (the ones used inside the devcontainer will be different) # # You can change the core instance the frontend connects to by passing the -c option. # For example: script/develop_and_serve -c https://myhost.duckdns.org:8123 @@ -28,6 +22,10 @@ # For example: script/develop_and_serve -p 8654 # Note that if you are running from a devcontainer, you will need to setup # port forwarding as well if you want to access it from the container host. +# +# WARNING: +# If you change the core url in between runs but preserve the port on which the +# frontend runs, you will need to logout to clear the session from the previous core. # Stop on errors set -e diff --git a/script/serve.js b/script/serve.js index 842fe10295d2..b3a940189040 100644 --- a/script/serve.js +++ b/script/serve.js @@ -1,32 +1,41 @@ +import { createProxyMiddleware } from "http-proxy-middleware"; import express from "express"; -import https from "https"; +import { fileURLToPath } from "url"; import fs from "fs"; +import http from "http"; +import https from "https"; import minimist from "minimist"; import path from "path"; -import { fileURLToPath } from "url"; +const inDevContainer = process.env.DEVCONTAINER !== undefined; const parsedArguments = { - c: "http://localhost:8123", - p: process.env.DEVCONTAINER !== undefined ? "8123" : "8124", + c: inDevContainer + ? "http://host.docker.internal:8123" + : "http://localhost:8123", + p: inDevContainer ? "8123" : "8124", ...minimist(process.argv.slice(2)), }; - -const coreUrl = - process.env.DEVCONTAINER !== undefined - ? parsedArguments.c.replace("/localhost:", "/host.docker.internal:") - : parsedArguments.c; +const coreUrl = parsedArguments.c; const port = parseInt(parsedArguments.p); - const repoDir = path.join(fileURLToPath(import.meta.url), "../.."); +// if the core uses https, also use https for serving to avoid problems +// with headers like Strict-Transport-Security +const useHttps = coreUrl.startsWith("https:"); +const frontendBase = `http${useHttps ? "s" : ""}://localhost`; -import { createProxyMiddleware } from "http-proxy-middleware"; +console.log(`Frontend is hosted on ${frontendBase}:${port}`); +if (inDevContainer && port === 8123) { + console.log( + `Frontend is available on container host as ${frontendBase}:8124` + ); +} +console.log(`Core is used from ${coreUrl}`); const coreProxy = createProxyMiddleware({ target: coreUrl, changeOrigin: true, ws: true, }); - const app = express(); app.use("/", express.static(path.join(repoDir, "hass_frontend"))); app.use("/api/hassio/app", express.static(path.join(repoDir, "hassio/build"))); @@ -43,10 +52,6 @@ app.get("*", (req, res) => { }); app.use("/", coreProxy); -// if the core uses https, also use https for serving to avoid problems -// with headers like Strict-Transport-Security -const useHttps = coreUrl.startsWith("https:"); - const appServer = useHttps ? https.createServer( { @@ -55,26 +60,24 @@ const appServer = useHttps }, app ) - : app; + : http.createServer(app); -const frontendBase = `http${useHttps ? "s" : ""}://localhost`; -appServer.listen(port, () => { - if (process.env.DEVCONTAINER !== undefined) { - console.log( - `Frontend is available inside container as ${frontendBase}:${port}` - ); - if (port === 8123) { - console.log( - `Frontend is available on container host as ${frontendBase}:8124` - ); - } - } else { - console.log(`Frontend is hosted on ${frontendBase}:${port}`); - } - console.log(`Core is used from ${coreUrl}`); +const appListener = appServer.listen(port, () => { + console.log("Starting development server"); +}); + +let connections = []; +appListener.on("connection", (connection) => { + connections.push(connection); + connection.on( + "close", + () => (connections = connections.filter((curr) => curr !== connection)) + ); }); process.on("SIGINT", function () { - console.log("Shutting down file server"); - process.exit(0); + console.log("Shutting down development server"); + appServer.close(); + // websockets are not closed automatically + connections.forEach((c) => c.end()); }); From c5b5b5c653d9bb6c6ffde37b1f3a3df31a6aeeda Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Sat, 7 Dec 2024 11:25:58 +0000 Subject: [PATCH 12/13] updated documentation after testing --- script/develop_and_serve | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/script/develop_and_serve b/script/develop_and_serve index 1108f4891162..b808ad00c1ed 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -25,7 +25,10 @@ # # WARNING: # If you change the core url in between runs but preserve the port on which the -# frontend runs, you will need to logout to clear the session from the previous core. +# frontend runs, you should logout before you make the switch. If you do not +# the frontend will just keep loading and timeout as it has a session that is not +# valid for the server. You can fix this if you forgot it by clearing the cookies +# for your development frontend. # Stop on errors set -e From 0d92bb9d24900c3e3f219b274d1af1b0c4f28c3a Mon Sep 17 00:00:00 2001 From: Marte Tassyns Date: Sat, 7 Dec 2024 12:04:02 +0000 Subject: [PATCH 13/13] fix github warning about exposing private key --- .gitignore | 2 ++ script/develop_and_serve | 5 +++++ script/serve.crt | 19 ------------------- script/serve.key | 28 ---------------------------- 4 files changed, 7 insertions(+), 47 deletions(-) delete mode 100755 script/serve.crt delete mode 100755 script/serve.key diff --git a/.gitignore b/.gitignore index 7de50364e700..31d7abd90a54 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ build/ dist/ /hass_frontend/ /translations/ +script/serve.key +script/serve.crt # yarn .yarn/* diff --git a/script/develop_and_serve b/script/develop_and_serve index b808ad00c1ed..bdb9bb9b2e7f 100755 --- a/script/develop_and_serve +++ b/script/develop_and_serve @@ -42,6 +42,11 @@ if [ ! -d "./hassio/build" ]; then hassio/script/build_hassio fi +if [ ! -f "./script/serve.crt" ]; then + echo Generating self signed localhost certificate + openssl req -x509 -newkey rsa:4096 -keyout "./script/serve.key" -out "./script/serve.crt" -sha256 -days 3650 -nodes -subj "/CN=localhost" +fi + ./script/develop & yarn serve "$@" \ No newline at end of file diff --git a/script/serve.crt b/script/serve.crt deleted file mode 100755 index 9466b90de748..000000000000 --- a/script/serve.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDDDCCAfSgAwIBAgIIfUe7tkwbkhEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UE -AxMJbG9jYWxob3N0MB4XDTIxMTIzMTA1NDgwMVoXDTIyMTIzMTA1NDgwMVowFDES -MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAxfND9r1VoBJON91dz2/60WfUJKSTkXEJItMU0ZvoIyWiH51DydFS8q2oM5zB -GQz92dRIaMQHz7TqHhRnZ/sOzqJ2ZOUGTWwzYt6I8Yq/sMimS421/ogsB5K3rYL0 -EvMfb33Wejt30krD6AtWf/a+Mz8GpmC1a+BE6nti7o0frvK5xNwTnOi/utY72tN1 -1rcVLFMVzJBf6o9X8cGEEAsyMiBr7HPAyRkP2k3PQE0icVuMSEc63KLzqYp9tLKO -6zgQNs1W2WbMxQ3CgEio3f5PMld56aMomUcxJ0Tn12n4YvyvwOu6DZVX3xHVvXHH -FyBny4OjKF31pl9HWqlzrRTM8QIDAQABo2IwYDAMBgNVHRMBAf8EAjAAMA4GA1Ud -DwEB/wQEAwIFoDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATAXBgNVHREBAf8EDTAL -gglsb2NhbGhvc3QwDwYKKwYBBAGCN1QBAQQBAjANBgkqhkiG9w0BAQsFAAOCAQEA -MnIxAm0k70OfJWMCN9FdiJW2zAScvmv/DywqPoJqTrEelnszrROK2XynS536JeXg -lbIhZRfKTA3IABgGdoG/6soQYfMGFAwaRKmXh+KchThLrtuck+tX30KHJFHxD4cX -Jf2sqSSz5ol3X+W0CgWxPUOklPX3MDrAJ++U43njokZd6Q3eqes+HQl1XRM8Jsla -xPXTsG++48aJl6l0Lz6hqTSA9z7H6ddC3NWWHz9vrpGem/oaMXfdftnD8VultQX4 -al/iGwwLMMinGAOYmYF8qCWbcj1YNkqI7Iiu8ZQCOLMwr3HDA9SAvLLprw18dWSy -K73E/ijgqgJ70XV3MNGlCw== ------END CERTIFICATE----- diff --git a/script/serve.key b/script/serve.key deleted file mode 100755 index 4fc46bbbab03..000000000000 --- a/script/serve.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDF80P2vVWgEk43 -3V3Pb/rRZ9QkpJORcQki0xTRm+gjJaIfnUPJ0VLyragznMEZDP3Z1EhoxAfPtOoe -FGdn+w7OonZk5QZNbDNi3ojxir+wyKZLjbX+iCwHkretgvQS8x9vfdZ6O3fSSsPo -C1Z/9r4zPwamYLVr4ETqe2LujR+u8rnE3BOc6L+61jva03XWtxUsUxXMkF/qj1fx -wYQQCzIyIGvsc8DJGQ/aTc9ATSJxW4xIRzrcovOpin20so7rOBA2zVbZZszFDcKA -SKjd/k8yV3npoyiZRzEnROfXafhi/K/A67oNlVffEdW9cccXIGfLg6MoXfWmX0da -qXOtFMzxAgMBAAECggEBAMKH97GCjaQ6eR3TcP6LiIzEIapFBjR3Rkgv8hSvx6jK -shGphlXOXVraKCNYmDdbGhk40lQK2bZYj38yBBEem4WcCQfMPq5VeAZgtWnSNeGw -viQfxsu13Lcwi0t8FwqMXMc/fkgvKujByta+Vap5vJ81//3/qiqygmeBDE9s5scQ -S4G6nBtnMxbw+nX/MpTRR/lpCI6oS3S22NzzkYuhMb24PGI2A7mDGXvIqe3TCzWJ -UYIznWvgBSE8VRmU/j3pSDsVPKh6YFYBiCy2Tnx4hr5gmuC/9oK8J53dPwsfa4aN -znwQ1pMTHnztMUZgYUYWU31g7Kf56lpZyadOtIDHf4UCgYEAyuUq/V61z3zp5ULd -QT0k5covLwX5h40Rbsc63BR1vtg6zpvnwDUgnA0pM6f5S5XgVN9+tr6jpTtB6URd -DFMouUInrun2GIwxqRNlgYHnxod4sxJ547gPK68skaXMjK6HHBKW/fNCZG1BXUxy -Hf9C3s0UdJ0Hztc9uu9FKEjTUfMCgYEA+cLELcEOwuuNW5H5FsK6JiapHVb10diu -3NtYaChov3xX0cPS5NblTTK2MAy1BzN7eYFFlQg8usrDsgYgMTaeUoGgBlCxU+n9 -yxqfOg/wF56F4NWlvYeMMPpLsjCu1wOSxJuduvRWb0XWgOTFfG4T0TviP+AAoaeX -uogEZu5w+osCgYBNCCkEPVslxbU/190NEdvaaqLzZX9RmZuOxZFxUUtLA+l/2+1n -KkSROuXzuMiLjAG594iydTrIVvE1UUFKlqAVhipu3GEU/NU17ilRvDJ1S6XlxxQE -AzOvUDjJq3s3xmOBowU0sZD5dAmnFIkXHn0S/iXQCHaYb1v+hy1omA2zRQKBgCaG -eXZJSjqc1PAkAxUUslwCKKHi8QYOc2KT3v4qBYZL6svrddNgpnwS73FX9HCI62nh -m9cSLzPs5OTH9x1APImjfwiaV9AGzuQOVjNBlBpAlIwKyIcEqoY/hX+V7NIztebn -zhuxZsfBMQYuw5ue6yWiJBMQPWiyDkByjKNH8ltjAoGAHbQPSyxpyfCWnQV9R1HQ -gsgVw/hrF8Lo+j8ULSGl3+jMqQbg65t16vw6tQInyUPm0frcCLBJZN948K66ysFB -8U2pgdI7kx51sOsIev0cb/0d5e6c/SXsPeQ1NYK6v+NeLfx5Rc74NASbuOfiYLQk -DzoK6WnUS6LVj6joil/0ckE= ------END PRIVATE KEY-----