[Bug]: Device blocked by CORS policy
Hardware
T-Beam, T-Deck, DIY
Connection Type
HTTP
Local or Hosted
https://client.meshtastic.org
Firmware Version
2.3.10.d19607b
Description
When connecting to a device with https://client.meshtastic.org I will get a CORS violation. It happens with both http (meshtasticjs and slippy app with device added to chrome://flags/#unsafely-treat-insecure-origin-as-secure) and https.
This also wasn't happening about a week ago.
My browser is: Chromium Version 126.0.6478.61 (Official Build) (64-bit)
Relevant console output
05:10:23:988 DEBUG [iMeshDevice:HttpConnection] Constructor 🔷 HttpConnection instantiated
index-BkiO76n_.js:77 05:10:23:990 DEBUG [iMeshDevice:HttpConnection] Ping Attempting device ping.
client.meshtastic.org/:1 Access to fetch at 'https://192.168.0.168/hotspot-detect.html' from origin 'https://client.meshtastic.org' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
index-BkiO76n_.js:89
GET https://192.168.0.168/hotspot-detect.html net::ERR_FAILED
ping @ index-BkiO76n_.js:89
connect @ index-BkiO76n_.js:89
(anonymous) @ index-BkiO76n_.js:412
(anonymous) @ index-BkiO76n_.js:89
await in (anonymous) (async)
Zk @ index-BkiO76n_.js:37
eC @ index-BkiO76n_.js:37
tC @ index-BkiO76n_.js:37
Qh @ index-BkiO76n_.js:37
y1 @ index-BkiO76n_.js:37
(anonymous) @ index-BkiO76n_.js:37
_p @ index-BkiO76n_.js:40
Uy @ index-BkiO76n_.js:37
fd @ index-BkiO76n_.js:37
X0 @ index-BkiO76n_.js:37
vC @ index-BkiO76n_.js:37
index-BkiO76n_.js:77 05:10:26:403 ERROR [iMeshDevice:HttpConnection] Ping ❌ Failed to fetch
index-BkiO76n_.js:77 05:10:36:404 DEBUG [iMeshDevice:HttpConnection] Ping Attempting device ping.
client.meshtastic.org/:1 Access to fetch at 'https://192.168.0.168/hotspot-detect.html' from origin 'https://client.meshtastic.org' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
index-BkiO76n_.js:89
GET https://192.168.0.168/hotspot-detect.html net::ERR_FAILED
ping @ index-BkiO76n_.js:89
connect @ index-BkiO76n_.js:89
(anonymous) @ index-BkiO76n_.js:89
setTimeout (async)
connect @ index-BkiO76n_.js:89
await in connect (async)
(anonymous) @ index-BkiO76n_.js:412
(anonymous) @ index-BkiO76n_.js:89
await in (anonymous) (async)
Zk @ index-BkiO76n_.js:37
eC @ index-BkiO76n_.js:37
tC @ index-BkiO76n_.js:37
Qh @ index-BkiO76n_.js:37
y1 @ index-BkiO76n_.js:37
(anonymous) @ index-BkiO76n_.js:37
_p @ index-BkiO76n_.js:40
Uy @ index-BkiO76n_.js:37
fd @ index-BkiO76n_.js:37
X0 @ index-BkiO76n_.js:37
vC @ index-BkiO76n_.js:37
index-BkiO76n_.js:77 05:10:38:587 ERROR [iMeshDevice:HttpConnection] Ping ❌ Failed to fetch
~~Bug is in the javascript, will detail then transfer to that repo, then fix~~
~~HTTPS is forced on for all HTTP connections, fixing now~~
I have found part of the issue, On chrome linux enabling chrome://flags/#enable-experimental-web-platform-features (needed for web-bluetooth support on linux) will cause the errors.
I ended up having to directly view https://meshtastic.local/ as https://client.meshtastic.org/ doesn't work because of the CORS policy.
I haven't attempted reproducing this yet, but FWIW https://github.com/meshtastic/firmware/pull/652 started and https://github.com/meshtastic/firmware/pull/656 added CORS support, albeit the * value (rather than repeating back the origin). MDN says this is valid only when credentials are not used. :thinking:
CORS headers should be present, as far as I can tell, from the node. I believe the issue is the no-cors mode we have set in js. However that also feels strange because it's been that way for a while and we haven't seen these issues. I don't have everything set up locally to test this, but if someone else does try just removing the no-cors mode or changing it to a different value.
Device: Linux Native, running in docker, with port 4430 forwarded to container port 443 (TLS) Client: https://client.meshtastic.org/
Firefox dev console Network tab shows request PUT /api/v1/toradio with "CORS Missing Allowed Origin".
Debugging using curl:
$ curl -v https://localhost:4430/api/v1/toradio -k -X OPTIONS
...
> OPTIONS /api/v1/toradio HTTP/1.1
> Host: localhost:4430
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Tue, 08 Oct 2024 17:19:05 GMT
< Content-Length: 18
<
but it is present on GET /:
$ curl -v https://localhost:4430/ -k
...
> GET / HTTP/1.1
> Host: localhost:4430
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Tue, 08 Oct 2024 17:16:40 GMT
< Access-Control-Allow-Origin: *
< Content-Length: 14
<
Ran meshtasticd under gdb, with breakpoint on handleAPIv1ToRadio, when sending method PUT, the breakpoint is hit. When sending method OPTIONS, the breakpoint is not hit.
Backtrace at handleAPIv1ToRadio:
(gdb) bt
#0 handleAPIv1ToRadio (req=0x7ff2c0004340, res=0x7ff2c0006620, user_data=0x5624234061a0) at src/mesh/raspihttp/PiWebServer.cpp:226
#1 0x00007ff2cf0cab16 in ?? () from /lib/x86_64-linux-gnu/libulfius.so.2.7
#2 0x00007ff2ce4ed1ac in ?? () from /lib/x86_64-linux-gnu/libmicrohttpd.so.12
#3 0x00007ff2ce4ef2f8 in ?? () from /lib/x86_64-linux-gnu/libmicrohttpd.so.12
#4 0x00007ff2ce4f1c9f in ?? () from /lib/x86_64-linux-gnu/libmicrohttpd.so.12
#5 0x00007ff2ce4f57ca in ?? () from /lib/x86_64-linux-gnu/libmicrohttpd.so.12
#6 0x00007ff2ce7b5144 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#7 0x00007ff2ce834a40 in clone () from /lib/x86_64-linux-gnu/libc.so.6
Ah looks like there's a second set of handlers for native platform (src/mesh/raspihttp/PiWebServer.cpp):
ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath);
and no endpoint for OPTIONS method.
Needs a patch like this:
commit 044466017a4afb9a27666ce36306bdf5d25f85c1 (HEAD -> master)
Author: Catalin Patulea <[email protected]>
Date: Tue Oct 8 14:06:41 2024 -0400
toradio: fix CORS
diff --git a/src/mesh/raspihttp/PiWebServer.cpp b/src/mesh/raspihttp/PiWebServer.cpp
index d7e59675..2227c958 100644
--- a/src/mesh/raspihttp/PiWebServer.cpp
+++ b/src/mesh/raspihttp/PiWebServer.cpp
@@ -232,7 +232,7 @@ int handleAPIv1ToRadio(const struct _u_request *req, struct _u_response *res, vo
ulfius_add_header_to_response(res, "X-Protobuf-Schema",
"https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto");
- if (req->http_verb == "OPTIONS") {
+ if (!strcmp(req->http_verb, "OPTIONS")) {
ulfius_set_response_properties(res, U_OPT_STATUS, 204);
return U_CALLBACK_CONTINUE;
}
@@ -493,6 +493,7 @@ PiWebServerThread::PiWebServerThread()
// Maximum body size sent by the client is 1 Kb
instanceWeb.max_post_body_size = 1024;
ulfius_add_endpoint_by_val(&instanceWeb, "GET", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL);
+ ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath);
ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath);
// Add callback function to all endpoints for the Web Server
FYI @jp-bennett