https://github.com/artkra/tranzit
Python3 micro web framework based on aiohttp supporting websockets.
https://github.com/artkra/tranzit
aiohttp async python3 web websocket-server websockets
Last synced: 25 days ago
JSON representation
Python3 micro web framework based on aiohttp supporting websockets.
- Host: GitHub
- URL: https://github.com/artkra/tranzit
- Owner: artkra
- License: gpl-2.0
- Created: 2017-09-24T19:42:54.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2021-03-25T21:50:40.000Z (about 5 years ago)
- Last Synced: 2025-12-16T11:57:04.840Z (6 months ago)
- Topics: aiohttp, async, python3, web, websocket-server, websockets
- Language: Python
- Homepage:
- Size: 173 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# What's that?
_**TRANZIT**_ is an asynchronous micro web framework supporting websockets
(full duplex socket communication). With **tranzit** you can easily maintain
both push & pull websocket messaging.
In fact, **tranzit** is a just a tiny wrapper for wonderful
**aiohttp** lib providing async websocket server (which can be run
separately) and a little *CLI* tool.
## Installation
You can install **tranzit** via pip:
$ pip install tranzit
## Quickstart
You can use *CLI* tool for that:
$ tranzit project
$ cd
$ tranzit run
Now your project runs on http://0.0.0.0:3000/ .
The first command creates a skeleton project:
```
/
__init__.py
apps/
__init__.py
hello/
__init__.py
static/
camel.html
common/
static/
tz.js
main.py
server.yml
```
The main.py file starts the whole thing. It gets configs from
*server.yml* such as:
* HTTP server host
* HTTP server port
* To start websocket server or not
* Websocket server host
* Websocket server port
* Which apps to run
* Is this a production start or not (not meaningful yet)
> **Info:** You should always pass PROJECT_DIR to *MainServer()*
constructor
## Routing and Views
All routing (for both http requests and websocket requests) is
handled by *apps/\/routes.py* file.
`PATH_PREFIX` variable contains prefix for urls handled by this
application (like [http://0.0.0.0:3000/\/some_url]).
`APP_STATIC_DIR` variable contains absolute path to the static
folder for this application.
All views for http requests are dispatched by *routes* dict.
Http views are ordinary **aiohttp** views.
All websocket views are dispatched by *ws_rules* dict.
See explanation below.
## Middlewares
You can pass a list of your middlewares in *main.py*:
```python
MainServer(
'server.yml', PROJECT_DIR, middlewares=[my_middleware]
)
```
More on **aiohttp** middlewares [here](https://docs.aiohttp.org/en/stable/web_advanced.html#middlewares).
## Staticfiles
There are two types of static files directories in the project skeleton.
The first is _**\/common/static/**_ . It contains
common project static files and is available via
http://0.0.0.0:3000/static/common/YOUR_GLORIOUS.js
The second type is app-specific:
_**\/apps/\/static**_ .
As you may suggest, it can be found here:
http://0.0.0.0:3000/static/APP_NAME/ANOTHER_GLORIOUS.js
## Few words about websockets
To establish websocket messaging you must add websocket rule in
apps/\/routes.py file just like that:
```python
ws_rules = {
'get_hello': WSPushHandle.get_hello
}
```
Now this view is available via websockets.
To call this view function, do something like this on the
client side:
```javascript
var ws = new WebSocket('ws://0.0.0.0:19719');
ws.onmessage = function(response) {
console.log(response.data);
};
ws.send('get_hello|');
```
We send message to call the view.
Here is an ugly syntax for that message:
`|arg1, arg2, arg3, ... `
Now take a look at the websocket view:
```python
class WSPushHandle(object):
@staticmethod
async def get_hello(*args, **kwargs):
send_func = kwargs['send_func']
writer = kwargs['writer']
while True:
await asyncio.sleep(1)
await send_func(writer, 'HELLO!')
```
Last line is a way to send message back to the client:
```python
await send_func(writer, 'HELLO!')
```
As you can see, `send_func` and `writer` instances are accessible via `**kwargs`.
> **Warning:** ~~beware of yellow snow!~~ all websocket routes are
in the same namespace! Avoid collisions.
> **Another warning:** No security provided! Be sure to verify
websocket request (e.g. pass user session key in WS view parameters)
## Using aiohttp module
All of `aiohttp.web` module is accessible via `tranzit.web`.
## Starting stand alone websocket server
You can use websocket server without http server.
All you need is an instance of:
*tranzit.web.WebSocketServer(host, port, api)*
*api* is a handler class instance which implements 3 functions
as shown below:
```python
class TranzitWSHandler(object):
async def handle_text(self, loop, writer, msg):
pass
async def handle_binary(self, loop, writer, msg):
pass
async def handle_buffered(self, loop, reader, writer, first_msg):
pass
```
Example starting stand alone websocket server:
```python
from tranzit.web import WebSocketServer
class MyHandler():
def __init__(self, rules={}):
self.rules = rules
async def handle_text(self, loop, writer, msg):
response = msg.upper()
await WebSocketServer.send_text(writer, response)
async def handle_binary(self, loop, writer, msg):
pass
async def handle_buffered(self, loop, reader, writer, first_msg):
pass
ws_server = WebSocketServer(
host='0.0.0.0', port=19719, api=MyHandler()
)
ws_server.run_forever()
```