crossbario / autobahn-python

WebSocket and WAMP in Python for Twisted and asyncio
https://crossbar.io/autobahn
MIT License
2.48k stars 768 forks source link

Support fully general websocket origin URLs #1302

Open Axel13fr opened 4 years ago

Axel13fr commented 4 years ago

Hi,

I'm embedding my webpage inside a QWebEngine (https://doc.qt.io/qt-5/qtwebengine-overview.html). This Webengine access local files via qrc:// instead of file:// for Chrome.

The problem is, the _url_to_origin(url) function does handle the Chrome or Firefox case but not the QWebengine page and I have no way to change the origin in my webengine so my websocket connections fail (('HTTP Origin header invalid: No host part in Origin 'qrc://'').

Adding this to _url_to_origin() will handle the case: if scheme == 'qrc':

when browsing local files, QtWebEngine sends qrc:// URLs

    return 'null'
oberstet commented 4 years ago

Oh, ok, I see. Yeah, to make websocket origin of exotic values like this work in general, I guess we need to expand

https://github.com/crossbario/autobahn-python/blob/108408cb1c274570e7e06f31427058a7b04c72fc/autobahn/websocket/protocol.py#L71

which is called from here during the websocket opening handshake to parse the origin:

https://github.com/crossbario/autobahn-python/blob/108408cb1c274570e7e06f31427058a7b04c72fc/autobahn/websocket/protocol.py#L2734

Actually, the relevant spec is https://tools.ietf.org/html/rfc6454 which is referred in RFC6455. That spec also draws a distinction between the sec-websocket-origin http header which has an URL value, and the websocket origin computed from the URL using the algorithm described here https://tools.ietf.org/html/rfc6454#section-4

One Q: does QtWebEngine really retun "qrc://" or eg "qrc://somefile.html" including whatever resourcename / filename the page is actually loaded from or rendered for?

Axel13fr commented 4 years ago

Thanks for your quick response, the QtWebEngine doesn't add any file name or ressource name, it only gives "qrc://" as the origin.

Here is the complete WS Upgrade request:

GET ws://127.0.0.1:9090/ HTTP/1.1 Host: 127.0.0.1:9090 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: qrc:// Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/5.9.5 Chrome/56.0.2924.122 Safari/537.36 Accept-Encoding: gzip, deflate, br Sec-WebSocket-Key: Rwj3a5FcsXdDygUHa1jo5w== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

oberstet commented 4 years ago

^ thanks for the info! that is useful, as it means: we might want a node config knob to configure the mapping of the URL provided as Origin to a websocket origin (a server-side context in which the websocket client connection is allowed and lives)

btw, Qt in general still seems to lack a bit rgd websocket standard compliance, eg websocket subprotocol handling https://bugreports.qt.io/browse/QTBUG-38742

the latter is relevant for WAMP, which uses wamp as identifier (https://www.iana.org/assignments/websocket/websocket.xml) ..

oberstet commented 4 years ago

luckily, we have already have an _url_to_origin() abstraction internally:

https://github.com/crossbario/autobahn-python/blob/108408cb1c274570e7e06f31427058a7b04c72fc/autobahn/websocket/protocol.py#L71

so all we need is to (enable) map of qrc:// to eg ('qrc', 'nohost', None) ..

we also already have a proper _is_same_origin() abstraction, which we can extend similarily

Axel13fr commented 4 years ago

Cheers for the info, I'll try to work on it in the following weeks