Skip to main content

Simple framework to create awesome WebSocket APIs

Project description

ringding - Simple framework to create awesome WebSocket APIs

What is ringding?

Ringding is a framework to communicate between a Python server and JavaScript client(s) based on WebSocket. Compared to Web API frameworks like Flask or FastAPI, the ringding API is specified in a more "Python-API-style" way using classes rather than using decorators and "magic strings". The call of API functions on the JavaScript side also looks more like function calls.

When do I want to use ringding?

  • When you want to call function on your server and don't want to provide a full-fledged REST-API.
  • When you want to minimize the overhead from HTTP-headers (especially in Single-Page-Applications / SPAs).
  • When you want to publish a Python-API to a JavaScript client.
  • When the server should notify the clients about events.

What technology does ringding use?

Ringding is transmitting the data using WebSockets.

How do I use ringding?

Ringding provides a JavaScript-client and a Python server. The JavaScript client ringdingjs is hosted by the server on the endpoint /client.js. But you can also extract ringdingjs.js from source and put it somewhere in your project. It is located in clients/js/ringdingjs.js. You will want to use the corresponding package.json for Node since Node not support WebSockets by default. If you want to use ringdingjs in browser apps, you don't need any dependencies.

An example Python backend:

import ringding


class MyApi:
    def get_name(self):
        return 'Alfred'
    
    def sum(self, a, b):
        return a + b


if __name__ == '__main__':
    ringding.RdServer(port=8001).serve(MyApi)

In NodeJS, you can use ringding like this:

const { RD, CallApi } = require('ringdingjs')

async function communicate() {
    await RD.connect('ws://localhost:8001')
    
    const name = await CallApi().MyApi.get_name()
    console.log('The name is', name)
    
    // You can provide keyword arguments to a function call.
    let sum = await CallApi().MyApi.sum({a: 5, b: 2})
    
    // You can also use the more flexible direct call:
    let another_sum = await RD.call("MyApi.sum(*)", {a: 4, b: 2}) 
    
    console.log('The sum is: ', sum)
    
    RD.disconnect()
}

communicate()

Alternatively in a browser, you can connect and call the sum-function like this:

<head>
    <meta charset="UTF-8">
    <title>Hello ringding</title>
</head>
<body>
    <div>Calling "API.sum()" with arguments {a: 5, b: 2}"</div>
    <div>Response: <span id="response"></span></div>
</body>
<script data-main="scripts/app" src="http://localhost:8001/client.js"></script>
<script>
    async function run_example() {

        // Connect to server
        await RD.connect('ws://localhost:8001')

        // Send a message
        const response = await CallApi().MyApi.sum({a: 5, b: 2})

        // Read the response
        console.log('Response:', response)
        document.getElementById('response').innerText = String(response)
    }
    run_example()
</script>
</html>

Other features

Chained calls

With chained calls you can call multiple parameterized functions on a server:

RD.call('Api.create_user(*user_data).get_hash(hash_type), {user_data: {name: 'Fido', age: 42}, hash_type: 'md5'}

Advanced return types

You can return every JSON-supported datatype (including lists and dicts with simple datatypes) or dataclasses.

import ringding

import dataclasses


@dataclasses.dataclass
class AdvancedReturnType:
    name: str
    age: int


class Api:
    def get_user(self):
        return AdvancedReturnType('Fido', 42)
    
if __name__ == '__main__':
    ringding.RdServer(port=8001).serve(Api)

The corresponding JavaScript call is this

const response = await CallApi().Api.get_user()
console.log(response.name) // "Fido"
console.log(response.age)  // 42

Nested APIs

I would recommend to use properties for nested Sub-API's on python side

import ringding


class Nested:
    def do_something(self):
        return 'I did something'

    
class Api:
    @property
    def NestedApi(self):
        return Nested()
    
if __name__ == '__main__':
    ringding.RdServer(port=8001).serve(Api)

And the JavaScript-call would be CallApi().Api.NestedApi.do_something()

A word on Typescript

You might want to create an own object of CallApi() and cast you API specification to that object. That way you could get an API with autocompletion powered by Typescript.

Roadmap

  • An interface to browse API's and their documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ringding-0.3.2.tar.gz (19.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ringding-0.3.2-py3-none-any.whl (22.5 kB view details)

Uploaded Python 3

File details

Details for the file ringding-0.3.2.tar.gz.

File metadata

  • Download URL: ringding-0.3.2.tar.gz
  • Upload date:
  • Size: 19.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.7.11

File hashes

Hashes for ringding-0.3.2.tar.gz
Algorithm Hash digest
SHA256 81f1e317082e8e1c0e3b09c99f04ee3262da563b9f9f87a75c3a7459ea5ed4a0
MD5 9d43f0da7a0496c34c2242910492b00b
BLAKE2b-256 f3ff128b7ee715b3af74a48c50e0035ee9dd18f09d10b7e58a205d72146cfef1

See more details on using hashes here.

File details

Details for the file ringding-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: ringding-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 22.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.7.11

File hashes

Hashes for ringding-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7a2e1060024ead02973eb9abc274eb126820033266c39c029af1da558dd75a00
MD5 d0682c59064a71eb1e93779df83023af
BLAKE2b-256 ca3f39f300e8f6fc183449da2c1be1cc07c28fd995d316e2525f0ee4b0aa9f23

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page