1

I'm building a simple HTTP web service, but I want to send information trough a websocket to another server.

For instance when the web service receive a request on /foo, it send on the websocket "request on /foo received".

I'm fairly new to async programming in Python. I choose aiohttp for this, but it's not a hard requirement.

I have some prior experience with websocket and autobahn and I tried at first to mix aiohtpp and autobahn. I even found an example with both but it used wamp and I just want websocket.

Then I tried without autobahn as aiohttp handle websocket.

My last attempt looks like that:

from aiohttp import web, ClientSession, WSMsgType

async def callback(msg):
    print(msg)

async def websocket(session):
    async with session.ws_connect('http://localhost:8000') as ws:
        app['ws'] = ws
        async for msg in ws:
            if msg.type == WSMsgType.TEXT:
                await callback(msg.data)
            elif msg.type == WSMsgType.CLOSED:
                break
            elif msg.type == WSMsgType.ERROR:
                break

async def hello(request):
    app.ws.send_str('{"hello": "world"}')
    return web.Response(text="Hello, world")

async def init(app):
    session = ClientSession()
    app['websocket_task'] = app.loop.create_task(websocket(session))

app = web.Application()
app.add_routes([web.get('/', hello)])
app.on_startup.append(init)
web.run_app(app, port=7000)

When requesting / it cashes with the following exception: AttributeError: 'Application' object has no attribute 'ws'

How can I mix http serving and writing on websocket as a client? Is it even possible ?

xav19
  • 61
  • 2
  • 6

1 Answers1

2

Sometimes a good night of sleep is all you need...

Basically I needed to initialize a resource and use it in the handlers. Exactly like you would do for a database connection.

I used this demo as an example and adapted it to my need. Here is what it looks like:

from aiohttp import web, ClientSession

class Handler:
    def __init__(self, ws):
        self._ws = ws

    async def hello(self):
        await self._ws.send_str('{"hello": "world"}')
        return web.Response(text="Hello, world")

async def init(app):
    session = ClientSession()
    ws = await session.ws_connect('http://localhost:8000')
    h = Handler(ws)
    app.add_routes([web.get('/', h.hello)])

app = web.Application()
app.on_startup.append(init)
web.run_app(app, port=7000)

I hope this can help other asyncio/aiohttp beginners.

Cheers

xav19
  • 61
  • 2
  • 6