Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Example with an async http server #46

Open
AdrienPensart opened this issue Dec 7, 2019 · 4 comments
Open

Example with an async http server #46

AdrienPensart opened this issue Dec 7, 2019 · 4 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@AdrienPensart
Copy link

Do you see an interest having examples with an async http server for authentication part ?

I struggle to have a working example with sanic but work is in progress.

@mental32 mental32 added enhancement New feature or request good first issue Good for newcomers labels Dec 14, 2019
@frafra
Copy link
Contributor

frafra commented Dec 15, 2019

Here is an example I wrote:

#!/usr/bin/env python3

from aiohttp import web
import os
import spotify

CLIENT_ID = os.environ['CLIENT_ID']
CLIENT_SECRET = os.environ['CLIENT_SECRET']
REDIRECT_URI = os.environ['REDIRECT_URI']

async def auth(request):
    async with spotify.Client(CLIENT_ID, CLIENT_SECRET) as client:
        url = client.oauth2_url(
            redirect_uri=REDIRECT_URI,
            scopes=['user-library-read'],
        )
        return web.HTTPFound(url)

async def callback(request):
    async with spotify.Client(CLIENT_ID, CLIENT_SECRET) as client:
        user = await spotify.User.from_code(
            client=client,
            code=request.query['code'],
            redirect_uri=REDIRECT_URI,
            )
    tracks = await user.library.get_all_tracks()
    return web.HTTPFound(repr(tracks))

app = web.Application()
app.add_routes([
    web.get('/', auth),
    web.get('/callback', callback),
])

if __name__ == '__main__':
    web.run_app(app)

@mental32
Copy link
Owner

mental32 commented Dec 15, 2019

Actually I wouldn't recommend that @frafra spotify.Client is made to me created once and carried around for the lifetime of the program. So creating and destroying instances on every route handler is a very expensive thing to do.

I'd suggesting using the contextvars module:

import asyncio
from contextvars import ContextVar

from aiohttp.web import AppRunner, TCPSite

CLIENT: ContextVar("spotify_client")

async def callback(request):
    client = CLIENT.get()
    user = await spotify.User.from_code(
        client=client,
        code=request.query['code'],
         redirect_uri=REDIRECT_URI,
    )
    tracks = await user.library.get_all_tracks()
    return web.HTTPFound(repr(tracks))


async def main() -> None:
    async with spotify.Client(CLIENT_ID, CLIENT_SECRET) as client:
        CLIENT.set(client)
        runner = AppRunner(app)
        await runner.setup()
        site = TCPSite(runner, 'localhost', 8080)
        await site.start()

if __name__ == "__main__":
    asyncio.run(main())

@frafra
Copy link
Contributor

frafra commented Dec 17, 2019

Using ContextVar is a good suggestion indeed :-)
The code looks incomplete to me now, as the auth part with the initial request and scopes is missing.

@mental32
Copy link
Owner

@frafra It was my intention that the codeblock I posted be combined with your one haha

would anyone like to PR this in themselves? Don't worry if not, I can add this is either way :)

@mental32 mental32 added the help wanted Extra attention is needed label Apr 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants