Search code examples
python-3.xpython-asyncioaiohttpetaglast-modified

How to send an etag or last modified while making a request with aiohttp session.get


  • I am loading multiple feed urls every minute
  • I want to send a http get request, get 200 status code and full data if the data has changed since the last time I loaded it
  • I want the http status code 304 and no response body if the data has not changed since the last time I loaded it
  • Python feedparser offers HERE this functionality if I use their library to send GET requests
  • How do I do this using aiohttp library
  • How do I send etag and last modified in the GET request

    async with session.get(url) as response:
        text = await response.text()
        print(response.headers.get('etag'), response.headers.get('Last-Modified'))
    

How do I send etag and last modified and simulate behavior similar to the library above?

UPDATE 1

Here is some detailed code

import asyncio
import aiohttp

async def load_feed(session, url):
    # Keep this an empty string for the first request
    etag = 'fd31d1100c6390bd8a1f16d2703d56c0'
    # Keep this an empty string for the first request
    last_modified='Mon, 11 May 2020 22:27:44 GMT'
    try:
        async with session.get(url, headers={'etag': etag, 'Last-Modified': last_modified}) as response:
            t = await response.text()
            print(response.headers.get('etag'), response.headers.get('Last-Modified'), response.status, len(t), response.headers)
    except Exception as e:
        print(e)

async def load_feeds():
    try:
        async with aiohttp.ClientSession() as session:
            tasks = []
            for url in ['https://news.bitcoin.com/feed/']:
                task = asyncio.ensure_future(load_feed(session, url))
                tasks.append(task)
            await asyncio.gather(*tasks, return_exceptions=True)
    except:
        pass

asyncio.get_event_loop().run_until_complete(load_feeds())

Expectation:

  • Send a request the first time without headers
  • Get a response code 200 with etag and Last-modified and full response
  • Send a request again with etag and Last-modified
  • Get a response code 304 with no response body

What is happening - I am getting status code 200 and full response body every time


Solution

  • Last-Modified is a response header, for a request you would use If-Modified-Since:

    async def load_feed(session, url):
        headers = {
            "ETag": "fd31d1100c6390bd8a1f16d2703d56c0",
            "If-Modified-Since": "Mon, 11 May 2020 22:27:44 GMT"
        }
        try:
            async with session.get(url, headers=headers) as response:
                t = await response.text()
                print(response.headers.get("ETag"), response.headers.get('Last-Modified'), response.status, len(t))
        except Exception as e:
            print(e)
    

    Output (notice status=304):

    "fd31d1100c6390bd8a1f16d2703d56c0" Mon, 11 May 2020 22:27:44 GMT 304 0