I'm trying to migrate an application with a lot of API calls (i.e. fetching data for a list of keys) to use asyncio as it's an IO-intensive task. This API requires NTLM authentication as it uses Active Directory credentials and I was using below code for this purpose:
session.auth = requests_ntlm.HttpNtlmAuth(username, password, session)
Apparently, asyncio uses aiohttp for asynchronous session handling. So synchronous, it works fine but trying to move it to a more desirable async/await flow, aiohttp only accepts basic auth credentials and would throw an error TypeError: BasicAuth() tuple is required instead if NTLM auth is passed to aiohttp.ClientSession. Here's the code sample for reference:
import asyncio
from aiohttp import ClientSession
from requests_ntlm import HttpNtlmAuth
async def fetch(url, session):
async with session.get(url) as response:
print(f"url: {url} ({response.status})")
return await response.read()
async def run():
url = "http://server/page/{}"
tasks = []
conn = aiohttp.TCPConnector(limit=10)
async with ClientSession(connector=conn) as session:
session.auth = HttpNtlmAuth(username, password, session) # <--- Passing NTLM auth
for page in range(100):
task = asyncio.ensure_future(fetch(url.format(page), session))
tasks.append(task)
responses = await asyncio.gather(*tasks)
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run())
loop.run_until_complete(future)
Is there any way to pass NTLM credentials to aiohttp session and make it work?
Well, there is 2 ways to to this.
1 way is not really good, 'cause it's using async tasks with
loop.run_in_executor().2 way is better, but I don't really know if it could work.
If you able to watch source files of HttpNtlmAuth, you can see that
HttpNtlmAuthclass is inherted fromrequests.auth.AuthBase()Let's see what is
AuthBase()is really about:So if I am right, the only thing
AuthBase()class do - checks if Auth hooks are callable. So basicly you need to implement it with yourself...