asynchronous http web framework based on aiohttp providing websocket server functionality
Project description
# 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.
<!-- TODO: all the rest of README-->
## Installation
You can install **tranzit** via pip:
$ pip install tranzit
## Quickstart
You can use *CLI* tool for that:
$ tranzit project <PROJECT_NAME>
$ cd <PROJECT_NAME>
$ tranzit run
Now your project runs on http://0.0.0.0:3000/ .
The first command creates a skeleton project:
```
<PROJECT_NAME>/
__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/\<app_name>/routes.py* file.
`PATH_PREFIX` variable contains prefix for urls handled by this
application (like [http://0.0.0.0:3000/\<PATH_PREFIX>/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 _**\<PROJECT_NAME>/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:
_**\<PROJECT_NAME>/apps/\<APP_NAME>/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/\<app_name>/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:
`<function_name>|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()
```
_**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.
<!-- TODO: all the rest of README-->
## Installation
You can install **tranzit** via pip:
$ pip install tranzit
## Quickstart
You can use *CLI* tool for that:
$ tranzit project <PROJECT_NAME>
$ cd <PROJECT_NAME>
$ tranzit run
Now your project runs on http://0.0.0.0:3000/ .
The first command creates a skeleton project:
```
<PROJECT_NAME>/
__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/\<app_name>/routes.py* file.
`PATH_PREFIX` variable contains prefix for urls handled by this
application (like [http://0.0.0.0:3000/\<PATH_PREFIX>/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 _**\<PROJECT_NAME>/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:
_**\<PROJECT_NAME>/apps/\<APP_NAME>/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/\<app_name>/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:
`<function_name>|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()
```
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
tranzit-0.1.1.tar.gz
(156.3 kB
view hashes)