Compare commits

...

5 Commits

Author SHA1 Message Date
7654bd1660 Fix DeprecationWarning on Python 3.10+
This is still compatible with Python 3.7+
2025-08-28 17:15:41 -04:00
9672e9d411 Merge pull request #1 from cmusatyalab/master
Add github action to build container and push it to ghcr
2023-11-15 22:25:12 -05:00
Jan Harkes
03e2d9c61c Add github action to build container and push it to ghcr 2022-10-05 13:28:35 -04:00
406a098a3c Add MIT license 2021-08-20 12:28:39 -04:00
e2f686310d Add README 2021-08-20 12:17:32 -04:00
7 changed files with 134 additions and 6 deletions

43
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Create and publish Docker images for tagged versions
on:
push:
tags:
- 'v*'
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-docker-image:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- name: Check out repository
uses: actions/checkout@v3
- name: Log into GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.output.labels }}

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
README.html
venv

View File

@@ -1,5 +1,18 @@
FROM python:3-alpine FROM python:3-slim
LABEL org.opencontainers.image.description='Unwebsockify is a TCP to WebSocket proxy/bridge -- like a reverse websockify.' \
org.opencontainers.image.source='https://github.com/jimparis/unwebsockify' \
org.opencontainers.image.licenses='MIT'
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONFAULTHANDLER=1 \
PYTHONHASHSEED=random \
PYTHONUNBUFFERED=1
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN pip install --no-cache-dir websockets
COPY unwebsockify.py ./ COPY requirements.txt .
ENTRYPOINT [ "python", "-u", "./unwebsockify.py" ] RUN pip install --no-cache-dir -r requirements.txt
COPY unwebsockify.py .
ENTRYPOINT [ "python", "./unwebsockify.py" ]

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2021 Jim Paris <jim@jim.sh>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

49
README.md Normal file
View File

@@ -0,0 +1,49 @@
Unwebsockify is a TCP to WebSocket proxy/bridge. It accepts a plain
TCP connection and connects to a WebSocket server, effectively adding
WS support to a client that does not natively support it. It is
essentially the opposite of
[websockify](https://github.com/novnc/websockify).
Note that this only handles simple byte streams of data, with no
support for conveying WebSockets message framing back to the client.
In most cases, **specifying the WebSockets subprotocol (via
`--subproto`) is necessary**, because the server expects it to match
some particular string.
# Install dependencies
Using a virtual environment:
python3 -m venv venv
venv/bin/pip install -r requirements.txt
venv/bin/python unwebsockify.py -h
Or use docker (or replace `docker` with `podman`):
docker build -t unwebsockify .
docker run -p 13232:13232 unwebsockify -h
# Usage
usage: unwebsockify.py [-h] [--port PORT] [--listen ADDR] [--subproto SUBPROTO] URL
positional arguments:
URL WebSocket URL (ws://.. or wss://..)
optional arguments:
-h, --help show this help message and exit
--port PORT, -p PORT TCP listen port
--listen ADDR, -l ADDR TCP listen address
--subproto SUBPROTO, -s SUBPROTO WebSocket subprotocol
# Example
Eclipse Mosquitto supports WebSockets on the server side, but not on
the client side (for bridging). To bridge two MQTT instances via
websockets, run unwebsockify on the client:
venv/bin/python unwebsockify.py --port 13232 --subproto mqtt wss://server/
and configure and run the MQTT client instance with e.g.
address 127.0.0.1:13232

1
requirements.txt Normal file
View File

@@ -0,0 +1 @@
websockets

View File

@@ -48,7 +48,7 @@ class Proxy:
async def handle_client(self, r, w): async def handle_client(self, r, w):
peer = w.get_extra_info("peername") peer = w.get_extra_info("peername")
print(f'{peer} connected') print(f'{peer} connected')
loop = asyncio.get_event_loop() loop = asyncio.get_running_loop()
try: try:
async with websockets.connect( async with websockets.connect(
self.url, subprotocols=self.subproto) as ws: self.url, subprotocols=self.subproto) as ws:
@@ -96,7 +96,8 @@ def main(argv):
args = parser.parse_args() args = parser.parse_args()
loop = asyncio.get_event_loop() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
proxy = Proxy(args.port, args.listen, args.url, args.subproto) proxy = Proxy(args.port, args.listen, args.url, args.subproto)
loop.run_until_complete(proxy.start()) loop.run_until_complete(proxy.start())
loop.run_forever() loop.run_forever()