Search on blog:

Python: How to use requests to send JSON data, POST data, args in url and files to server aiohttp.web

JSON data

requests uses json= to send JSON and it automatically convert dictionary and add header 'Content-Type': 'application/json'.

import requests

r = requests.post('http://0.0.0.0:8080/test', json={'param1': 'value1', 'param2': 'value2'})

The same with standard data= .

import requests
import json

r = requests.post('http://0.0.0.0:8080/test', 
                  data=json.dumps({'param1': 'value1', 'param2': 'value2'}),
                  headers={'Content-Type': 'application/json'},
                 )

aiohttp.web receives it as await request.json(). It may raise error when there is no JSON data. It reads from stream so it may raise error if other function already read data from stream.

from aiohttp import web


routes = web.RouteTableDef()


@routes.post('/test')
async def test(request):

    try:
        print('JSON:', await request.json())  # json data as dictionary/list
    except Exception as ex:
        print('JSON: ERROR:', ex)

    return web.Response(text='Received...')


app = web.Application()
app.add_routes(routes)

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

POST data

requests uses data= to send as standard POST data.

import requests

r = requests.post('http://0.0.0.0:8080/test', data={'param1': 'value1', 'param2': 'value2'})

aiohttp.web receives it as await request.post(). It doesn't raise error when there is no POST data. It reads from stream so it gives empty data if other function already read data from stream.

from aiohttp import web


routes = web.RouteTableDef()


@routes.post('/test')
async def test(request):

    print('POST       :', await request.post())         # POST data

    return web.Response(text='Received...')


app = web.Application()
app.add_routes(routes)

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

Arguments in URL

requests uses params= to send values in url. It will automatically uses urllib.parse to convert it to string ?param1=value1&param2=value2. If there are special chars then it will use values %code

import requests

r = requests.post('http://0.0.0.0:8080/test', params={'param1': 'value1', 'param2': 'value2'})

aiohttp.web receives it as request.query_string (as string ?param1=value1&param2=value2) or request.query (as dictionary {'param1': 'value1', 'param2': 'value2'}). It doesn't raise error when there is no arguments in url. It doesn't read from stream so there is no conflict with other functions.

from aiohttp import web


routes = web.RouteTableDef()


@routes.post('/test')
async def test(request):

    print('ARGS string:', request.query_string)  # arguments in URL as string
    print('ARGS       :', request.query)         # arguments in URL as dictionary

    return web.Response(text='Received...')


app = web.Application()
app.add_routes(routes)

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

FILES

requests uses files= to send files. It uses list with tuples. Every tuple describes on file. It has field's name (like in form in HTML), file handler (open(...)) or file data (open(...).read())

import requests

r = requests.post('http://0.0.0.0:8080/test', files=[('file', open('client.py'))])

aiohttp.web receives it as await request.multipart(). It raise error when there is no files. It reads from stream so it may raise error if other function already read data from stream.

from aiohttp import web


routes = web.RouteTableDef()


@routes.post('/test')
async def test(request):

    try:
        #print('MULTIPART:', await request.multipart())  # files and forms
        reader = await request.multipart()
        print('MULTIPART:', reader)
        while True:
            part = await reader.next()
            if part is None: 
                break
            print('filename:', part.filename)
            print('>>> start <<<')
            print(await part.text())
            print('>>> end <<<')
    except Exception as ex:
        print('MULTIPART: ERROR:', ex)

    return web.Response(text='Received...')


app = web.Application()
app.add_routes(routes)

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

BODY

aiohttp.web has also methods to read raw data from body. They don't raise error but they may gives empty data if other function already read data from stream.

    print('BODY bytes :', await request.content.read())  # body as bytes
    print('BODY string:', await request.text())          # body as string

Notes:

URL POST JSON FILE BODY
async/stream/body NO YES YES YES YES
raise error NO NO YES YES NO

Functions which read from stream (POST, JSON, FILE, BODY) may not get data if other of these functions already read data.


Original question on Stackoverflow: aiohttp.web post method get params

If you like it
Buy a Coffee