I am trying to add websockets to my app. I use JWT tokens so I have to overide middleware for it.
#database_sync_to_async
def get_user(token):
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=ALGORITHM)
except:
return AnonymousUser()
token_exp = datetime.fromtimestamp(payload['exp'])
if token_exp < datetime.utcnow():
return AnonymousUser()
try:
response = requests.get(settings.OAUTH_URL, headers={'Authorization': f"Bearer {token}"})
if response.status_code == 200:
user = response.json()
return user
except:
error_logger.exception("Server is not available!")
class TokenAuthMiddleware(BaseMiddleware):
async def __call__(self, scope, receive, send):
close_old_connections()
try:
token_key = (dict((x.split('=') for x in scope['query_string'].decode().split("&")))).get('token', None)
except ValueError:
token_key = None
scope['user'] = await get_user(token_key)
return await super().__call__(scope, receive, send)
def JwtAuthMiddlewareStack(inner):
return TokenAuthMiddleware(AuthMiddlewareStack(inner))
My service is a microservice so the User model is located in another service. So I have to send a request to the service where the instance model is located. When I try to add "user" dict-like object to scope it returns me an error:
helpdesk_web | File "/usr/local/lib/python3.10/site-packages/channels/auth.py", line 176, in resolve_scope
helpdesk_web | scope["user"]._wrapped = await get_user(scope)
helpdesk_web | AttributeError: 'dict' object has no attribute '_wrapped'
If I delete this line scope['user'] = await get_user(token_key) or pass to the function model instance everything works.
Is there a way to add 'users' dict-like object instead of model instance to scope?
Related
I am working on building an asyncio.Future integration with my Tornado app so I can request a callback. Essentially, I instantiated a class within a class, this creates a future and adds a callback to the function.
However, when I call this I get a bunch of error messages:
Traceback (most recent call last):
File "/Users/robot/tornado/venv/lib/python3.8/site-packages/tornado/web.py", line 1713, in _execute
result = await result
File "pending/request_seven.py", line 31, in get
await self.scheduleFuture._future(client.fetch('https://books.toscrape.com'), self.on_response)
File "pending/request_seven.py", line 25, in _future
fut = self.create_future()
AttributeError: '_asyncio.Future' object has no attribute 'create_future'
Here is what I have tried with my script:
define('port', default = 9057, help="run port 9060", type=int)
class requestFour(tornado.web.RequestHandler):
class scheduleFuture(asyncio.SelectorEventLoop):
#staticmethod
def unwrapper(fut: asyncio.Future, function):
return function()
def _future(self, fun1 ):
fut = self.create_future()
fut.add_done_callback(func(self.unwrapper, function=fun1))
return fut
async def get(self):
client = tornado.httpclient.AsyncHTTPClient()
await self.scheduleFuture._future(client.fetch('https://books.toscrape.com'), self.on_response)
def on_response(self, response):
body = response.body
self.write(body)
self.finish()
def my_app():
app = tornado.web.Application(handlers = [(r'/', requestFour)])
http_server = tornado.httpserver.HTTPServer(app)
return http_server
async def main():
app = my_app()
app.listen(options.port)
shutdown_event = asyncio.Event()
await shutdown_event.wait()
if __name__ == '__main__':
asyncio.run(main())
#bot.command(aliasses=['QUEUE', 'queue', 'q', 'Q'])
async def queue(ctx):
member = ctx.message.author
voice_state = ctx.member.voice
QAPI = ctx.message.author.id
if voice_state is None:
await ctx.send(f'You need to be in "<#1022558265348980796>" Channel to use that ')
else:
await ctx.send(f'You been putted in Queue. "<#{QAPI}')
AttributeError: 'Context' object has no attribute 'member'
i can't get it. i setted the member, i specify what is voice_state.. any ideeas?
I am new to Django so I figure this question could be a bit stupid.I have an api endpoint that returns a list of Doctors(and their details) and another that returns one doctor(and his details)-this is the call am trying to make.I think the issue I am having is with how to ref the pk in the request url.
As it is, when I test on postman I get the error {
"errors": "JSONDecodeError('Expecting value: line 1 column 1 (char 0)',)",
"status": "error"
}
I am almost certain the issue is in api_services.py.I really hope someone can just point it out to me.
views.py
`class FinanceDoctorsView(GenericAPIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
#classmethod
#encryption_check
def get(self, request, *args, **kwargs):
response = {}
pk = kwargs.get("pk")
try:
result = {}
auth = cc_authenticate()
res = getDoctorInfo(auth["key"], pk)
result = res
return Response(result, status=status.HTTP_200_OK)
except Exception as e:
error = getattr(e, "message", repr(e))
result["errors"] = error
result["status"] = "error"
return Response(result, status=status.HTTP_400_BAD_REQUEST)`
api_services.py
import requests
def getDoctorInfo(auth, params):
print("getting doctorInfo from Callcenter")
try:
headers = {
"Authorization": f'Token {auth}'
}
url = f'{CC_URL}/finance/doctor-info/<int:pk>'
res = requests.get(url, headers=headers)
print("returning doctorInfo response", res.status_code)
return res.json()
except ConnectionError as err:
print("connection exception occurred")
print(err)
return err
urls.py
path(
"doctor-info/<int:pk>", views.FinanceDoctorsView.as_view(), name="doctor_info"
),
I think in the api service file, you have made a typo
url = f'{CC_URL}/finance/doctor-info/<int:pk>'
Should had be
# as in the function you have defined params,
# and I think it could have been renamed as pk
url = f'{CC_URL}/finance/doctor-info/{params}'
I'm a complete beginner when it comes to socket, so please bear with me if the question seems too trivial for you.
The following is a code that i found on GitLab and I'm trying to understand
import os
import logging
import uuid
import socketio
from aiohttp import web
import sys
sys.path.append('.')
logging.basicConfig(level=logging.WARN,
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt='%m-%d %H:%M')
# Home page
async def index(request):
index_file = open('examples/rasa_demo/templates/index.html')
return web.Response(body=index_file.read().encode('utf-8'), headers={'content-type': 'text/html'})
# Action endpoint
async def webhook(request):
"""Webhook to retrieve action calls."""
action_call = await request.json()
try:
response = await executor.run(action_call)
except ActionExecutionRejection as e:
logger.error(str(e))
response = {"error": str(e), "action_name": e.action_name}
response.status_code = 400
return response
return web.json_response(response)
# Web app routing
app = web.Application()
app.add_routes([
web.get('/', index),
web.post('/webhook', webhook),
web.static('/static', 'examples/rasa_demo/static')
])
# Instantiate all bot agents
bots = BotFactory.createAll()
# Websocket through SocketIO with support for regular HTTP endpoints
sio = socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')
sio.attach(app)
#sio.on('session_request')
async def on_session_request(sid, data):
if data is None:
data = {}
if 'session_id' not in data or data['session_id'] is None:
data['session_id'] = uuid.uuid4().hex
await sio.emit('session_confirm', data['session_id'])
#sio.on('user_uttered')
async def on_user_uttered(sid, message):
custom_data = message.get('customData', {})
lang = custom_data.get('lang', 'en')
user_message = message.get('message', '')
bot_responses = await bots[lang].handle_text(user_message) #await BotFactory.getOrCreate(lang).handle_text(user_message)
for bot_response in bot_responses:
json = __parse_bot_response(bot_response)
await sio.emit('bot_uttered', json, room=sid)
What I'm trying to understand is how do the event handlers catch or events like 'session_request' or'user_uttered' when they were never emitted.
Thank you.
I am new at Aiohttp and here is a client code for populating data. Below a server code for recieving data. But at server end I am getting KeyError. Also see print(len(request.post()) # server is 0. But this server code works with Postman testing. And this client code works well with "/httpbin/post/" request. What is wrong with this code. helps appreciated very much.
AT CLIENT SIDE
BASE_URL = "http://127.0.0.1:9001/"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
}
data = {'username': 'achama', 'password': 'password'}
register_endpoint = "register"
jar = aiohttp.CookieJar(unsafe=True)
async def main():
async with aiohttp.ClientSession(json_serialize=ujson.dumps, cookie_jar=jar) as session:
async with session.post(url=BASE_URL+register_endpoint, json=data, headers=headers) as resp:
resp_data = await resp.json(content_type=None)
print(resp_data)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Zero-sleep to allow underlying connections to close
loop.run_until_complete(asyncio.sleep(0))
loop.close()
AT SERVER
async def register(self, request):
print(len(await request.post()))
posted_data = await request.post()
user_id = await db.get_user_id(self.mongo.loginhub,
posted_data['username'])
if user_id is None:
hashed_password = generate_password_hash(posted_data['password'])
await self.mongo.loginhub.insert_one(
{'username': posted_data['username'],
'current_password': hashed_password,
'last_password': ""})
unique_id = await db.get_user_id(self.mongo.loginhub, posted_data['username'])
await self.mongo.users.insert_one(
{'unique_id': unique_id, 'username': posted_data['username'],
"joined_date": datetime.utcnow(), "active": False})
return json_response({"message": f"Your account created with {posted_data['username']} Please login to use."})
else:
return json_response({"Error": f"Username {posted_data['username']} already exists. Please choose another one."})
SERVER SIDE ERROR
File "/home/bijuknarayan/workspace/aio/marryapp/backend/auth.py",
line 44, in register
user_id = await db.get_user_id(self.mongo.loginhub, posted_data['username']) File "multidict/_multidict.pyx", line 62,
in multidict._multidict._Base.getitem File
"multidict/_multidict.pyx", line 57, in
multidict._multidict._Base._getone File "multidict/_multidict.pyx",
line 52, in multidict._multidict._Base._getone KeyError: 'username'
Replace await request.post() with await request.json() on the server side if you want to handle JSON data.