-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trunk 0.21.6 causes CORS related issues when used with tauri, which causes CSS attributes not being applied #941
Comments
It could be related to #934. |
I had a look, and the final index.html in my-app/dist/ <!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Tauri + Leptos App</title>
<link rel="stylesheet" href="/styles-8594f9560b2c9a3f.css" integrity="sha384-LDfuJQTxLxRuEDdPgbqdtWGmnRQovfvNZuMp/F1Ds/8UBwItKMXhlpp3ghq7IX7O"/>
<script type="module" nonce="{{__TRUNK NONCE__}}">
import init, * as bindings from '/my-app-ui-196185f181692e60.js';
const wasm = await init({ module_or_path: '/my-app-ui-196185f181692e60_bg.wasm' });
window.wasmBindings = bindings;
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
</script>
<link rel="modulepreload" nonce="{{__TRUNK NONCE__}}" href="/my-app-ui-196185f181692e60.js" crossorigin="anonymous" integrity="sha384-rxudMjVa+yAnfjnpHmwNWAlp/jSCTM9XEaMgRL2VrWHuW2R38mWNrRz3WVUYfL+F"><link rel="preload" nonce="{{__TRUNK NONCE__}}" href="/my-app-ui-196185f181692e60_bg.wasm" crossorigin="anonymous" integrity="sha384-ppqX7J+rRF3sVGuknVh5JnGHrJA6cVi91GlzbzXC3JKgfKk6N1rlYTQYEMkGBuK2" as="fetch" type="application/wasm"></head>
<body><script nonce="{{__TRUNK NONCE__}}">"use strict";
(function () {
const address = '{{__TRUNK_ADDRESS__}}';
const base = '{{__TRUNK_WS_BASE__}}';
let protocol = '';
protocol =
protocol
? protocol
: window.location.protocol === 'https:'
? 'wss'
: 'ws';
const url = protocol + '://' + address + base + '.well-known/trunk/ws';
class Overlay {
constructor() {
// create an overlay
this._overlay = document.createElement("div");
const style = this._overlay.style;
style.height = "100vh";
style.width = "100vw";
style.position = "fixed";
style.top = "0";
style.left = "0";
style.backgroundColor = "rgba(222, 222, 222, 0.5)";
style.fontFamily = "sans-serif";
// not sure that's the right approach
style.zIndex = "1000000";
style.backdropFilter = "blur(1rem)";
const container = document.createElement("div");
// center it
container.style.position = "absolute";
container.style.top = "30%";
container.style.left = "15%";
container.style.maxWidth = "85%";
this._title = document.createElement("div");
this._title.innerText = "Build failure";
this._title.style.paddingBottom = "2rem";
this._title.style.fontSize = "2.5rem";
this._message = document.createElement("div");
this._message.style.whiteSpace = "pre-wrap";
const icon= document.createElement("div");
icon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="#dc3545" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg>';
this._title.prepend(icon);
container.append(this._title, this._message);
this._overlay.append(container);
this._inject();
window.setInterval(() => {
this._inject();
}, 250);
}
set reason(reason) {
this._message.textContent = reason;
}
_inject() {
if (!this._overlay.isConnected) {
// prepend it
document.body?.prepend(this._overlay);
}
}
}
class Client {
constructor(url) {
this.url = url;
this.poll_interval = 5000;
this._overlay = null;
}
start() {
const ws = new WebSocket(this.url);
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
switch (msg.type) {
case "reload":
this.reload();
break;
case "buildFailure":
this.buildFailure(msg.data)
break;
}
};
ws.onclose = () => this.onclose();
}
onclose() {
window.setTimeout(
() => {
// when we successfully reconnect, we'll force a
// reload (since we presumably lost connection to
// trunk due to it being killed, so it will have
// rebuilt on restart)
const ws = new WebSocket(this.url);
ws.onopen = () => window.location.reload();
ws.onclose = () => this.onclose();
},
this.poll_interval);
}
reload() {
window.location.reload();
}
buildFailure({reason}) {
// also log the console
console.error("Build failed:", reason);
console.debug("Overlay", this._overlay);
if (!this._overlay) {
this._overlay = new Overlay();
}
this._overlay.reason = reason;
}
}
new Client(url).start();
})()
</script></body>
</html> When build with trunk 0.21.5, the index.html contains the following: <!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Tauri + Leptos App</title>
<link rel="stylesheet" href="/styles-8594f9560b2c9a3f.css" integrity="sha384-LDfuJQTxLxRuEDdPgbqdtWGmnRQovfvNZuMp/F1Ds/8UBwItKMXhlpp3ghq7IX7O"/>
<script type="module" nonce="jlMPf6PCM5FY8bkSfqmSnw==">
import init, * as bindings from '/my-app-ui-196185f181692e60.js';
const wasm = await init({ module_or_path: '/my-app-ui-196185f181692e60_bg.wasm' });
window.wasmBindings = bindings;
dispatchEvent(new CustomEvent("TrunkApplicationStarted", {detail: {wasm}}));
</script>
<link rel="modulepreload" href="/my-app-ui-196185f181692e60.js" crossorigin=anonymous integrity="sha384-rxudMjVa+yAnfjnpHmwNWAlp/jSCTM9XEaMgRL2VrWHuW2R38mWNrRz3WVUYfL+F"><link rel="preload" href="/my-app-ui-196185f181692e60_bg.wasm" crossorigin=anonymous integrity="sha384-ppqX7J+rRF3sVGuknVh5JnGHrJA6cVi91GlzbzXC3JKgfKk6N1rlYTQYEMkGBuK2" as="fetch" type="application/wasm"></head>
<body><script>"use strict";
(function () {
const address = '{{__TRUNK_ADDRESS__}}';
const base = '{{__TRUNK_WS_BASE__}}';
let protocol = '';
protocol =
protocol
? protocol
: window.location.protocol === 'https:'
? 'wss'
: 'ws';
const url = protocol + '://' + address + base + '.well-known/trunk/ws';
class Overlay {
constructor() {
// create an overlay
this._overlay = document.createElement("div");
const style = this._overlay.style;
style.height = "100vh";
style.width = "100vw";
style.position = "fixed";
style.top = "0";
style.left = "0";
style.backgroundColor = "rgba(222, 222, 222, 0.5)";
style.fontFamily = "sans-serif";
// not sure that's the right approach
style.zIndex = "1000000";
style.backdropFilter = "blur(1rem)";
const container = document.createElement("div");
// center it
container.style.position = "absolute";
container.style.top = "30%";
container.style.left = "15%";
container.style.maxWidth = "85%";
this._title = document.createElement("div");
this._title.innerText = "Build failure";
this._title.style.paddingBottom = "2rem";
this._title.style.fontSize = "2.5rem";
this._message = document.createElement("div");
this._message.style.whiteSpace = "pre-wrap";
const icon= document.createElement("div");
icon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="#dc3545" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg>';
this._title.prepend(icon);
container.append(this._title, this._message);
this._overlay.append(container);
this._inject();
window.setInterval(() => {
this._inject();
}, 250);
}
set reason(reason) {
this._message.textContent = reason;
}
_inject() {
if (!this._overlay.isConnected) {
// prepend it
document.body?.prepend(this._overlay);
}
}
}
class Client {
constructor(url) {
this.url = url;
this.poll_interval = 5000;
this._overlay = null;
}
start() {
const ws = new WebSocket(this.url);
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
switch (msg.type) {
case "reload":
this.reload();
break;
case "buildFailure":
this.buildFailure(msg.data)
break;
}
};
ws.onclose = this.onclose;
}
onclose() {
window.setTimeout(
() => {
// when we successfully reconnect, we'll force a
// reload (since we presumably lost connection to
// trunk due to it being killed, so it will have
// rebuilt on restart)
const ws = new WebSocket(this.url);
ws.onopen = () => window.location.reload();
ws.onclose = this.onclose;
},
this.poll_interval);
}
reload() {
window.location.reload();
}
buildFailure({reason}) {
// also log the console
console.error("Build failed:", reason);
console.debug("Overlay", this._overlay);
if (!this._overlay) {
this._overlay = new Overlay();
}
this._overlay.reason = reason;
}
}
new Client(url).start();
})()
</script></body>
</html> |
According to changes in #934 there is a config option to disable nonce generation, but unfortunately it didn't make it into the documentation, and there is no example entry in the top level Trunk.toml. I guess when building an app that later loads the HTML from the disc or other means of embedding, the nonce generation makes no sense, as there is no trunk process running in that case, to replace those placeholders. I'm not sure whether it makes sense to have a nonce generation enabled when developing locally, as the html page might not be loaded through trunk in that case either. I'm not sure how the tauri app loads the html page in that case. I'll investigate further tomorrow. This might have some implications for tauri apps using leptos. As those would need to update their Trunk.toml to include disabling nonce generation. |
I'm running into the issue as well. |
[build] |
Thanks for reporting and analyzing this. Indeed, that seems to be introduced by #934. I think the problem is: Line 193 in 16cf708
I think the solution would be to make this
|
Ok, just peeking at bit on how to use CSP nonces …
– https://content-security-policy.com/nonce/ So, indeed it should be a placeholder. However, I think it makes sense to set the |
As the nonce should be unique per request, it doesn't make sense to enable this by default, as that requires additional work on the serving side. On the other side, having a (static) random value isn't correct either. So we keep the current logic, but disable nonce generation by default, making it opt-in. Closes trunk-rs#941
As the nonce should be unique per request, it doesn't make sense to enable this by default, as that requires additional work on the serving side. On the other side, having a (static) random value isn't correct either. So we keep the current logic, but disable nonce generation by default, making it opt-in. Closes trunk-rs#941
It would be great if any of you could try out PR #942 to verify the fix. You can install it using: cargo install --git https://github.com/ctron/trunk trunk --branch hotfix/fix_941_1 |
Tried it out and indeed, that fixes the issue. |
Patch is working for me, too. Thanks! |
As the nonce should be unique per request, it doesn't make sense to enable this by default, as that requires additional work on the serving side. On the other side, having a (static) random value isn't correct either. So we keep the current logic, but disable nonce generation by default, making it opt-in. Closes trunk-rs#941
As the nonce should be unique per request, it doesn't make sense to enable this by default, as that requires additional work on the serving side. On the other side, having a (static) random value isn't correct either. So we keep the current logic, but disable nonce generation by default, making it opt-in. Closes #941
The build for the release |
#934 was written for this purpose: when application defines a CSP, all The existence of the nonce itself should not matter (e.g. older trunk versions added already a static, difficulty to replace Problem in this issue is probably the CSP generation (which was added and enabled by default also in #934). I do not know what tauri is doing; perhaps it adds manually some style or script or so to
I does not matter whether it is an own application or trunk. Replacement operation has been implemented in trunk and it is trivial to do this in custom applications.
imo it is a good idea to make the developing environment similar to the production one and detect CSP related problems early.
might be an alternative way |
I think that the previous behavior, being able to insert that placeholder (or any other value) should still be possible. I agree that it would be great to have some default, random, generated nonce for |
I'm not agains having those options, but in an application where there is no external access to any websites at all, only local html and and some wasm and some js glue code to talk to a backend that only does local networking CSP is totally out of the window for me. |
What I could observe so far:
After updating trunk to 0.21.6, all styles used in were somehow not applied. I can observe the following errors in developer tools, when enabled in debug mode:
Steps to reproduce:
Expect something similar to the following screenshot to be shown:
Actual result:
The issue is reproducible on linux and on windows.
In the meantime I went back to 0.21.5 which works fine, and doesn't cause those issues.
The text was updated successfully, but these errors were encountered: