Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[client] 301 in POST gets redirected to GET #3082

Closed
panagiks opened this issue Jun 14, 2018 · 4 comments
Closed

[client] 301 in POST gets redirected to GET #3082

panagiks opened this issue Jun 14, 2018 · 4 comments
Labels

Comments

@panagiks
Copy link
Contributor

Long story short

Using aiohttp-client to make a POST request, if the server responds with a 301 the client makes a new request to the provided URI but the new request is an empty GET.

Expected behaviour

According to RFC2616-sec10.3.2 the method should not change. Emphasis on:

When automatically redirecting a POST request after
receiving a 301 status code, some existing HTTP/1.0 user agents
will erroneously change it into a GET request.

Actual behaviour

According to RFC1945-sec9.3, RFC2068-sec10.3 and RFC2616-sec10.3:

The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD

Now, considering the in-code nature of aiohttp-client (i.e. it's not exactly an end-user user-agent) and the fact that aiohttp-client provides an option to not follow redirects, one could argue that the above should not strictly apply.

So, the way I see it there are two choices:

  • Maintain the HTTP method when redirecting (this is what happens for example when aiohttp-client gets a 308 during a POST request)

  • Do not redirect on any method other that GET and HEAD (event if follow redirects is True)

Steps to reproduce

Using the following server - client pair

import asyncio

from aiohttp import web

async def rt(request):
    return web.HTTPOk()

@web.middleware
async def print_request(request, handler):

    print(request)
    return (await handler(request))

async def get_app():
    middlewares = [print_request, web.web_middlewares.normalize_path_middleware()]
    app = web.Application(middlewares=middlewares)
    app.router.add_route('POST', '/rt/', rt)
    return app

web.run_app(get_app())
import aiohttp
import asyncio

async def pt():
    async with aiohttp.ClientSession() as session:
        async with session.post('http://localhost:8080/rt', data=b'data') as resp:
            print(resp.status)

asyncio.get_event_loop().run_until_complete(pt())

The client will print:

405

Indicating a Method Not Allowed (since it used GET on the resource)

and the server will print:

<Request POST /rt >                                 
<Request GET /rt/ >

Indicating that after the first POST on the resource the client tried to GET the resource returned by the server.

Your environment

Ubuntu 17.10
aiohttp 3.3.1

@asvetlov
Copy link
Member

The change was introduced by #157 (3.5 years ago).
I doubt if we need to break existing behavior.
I can argue that if you have to keep HTTP method you can use allow_redirects=False

@panagiks
Copy link
Contributor Author

I've already worked around this for my use case so this is not really causing me any issues.

Just notice that the behavior was not falling strictly under rfc and thought I'd report it.

If the behavior is intentional or you prefer not to make any change feel free to close the issue :)

@asvetlov
Copy link
Member

The behavior follows requests design.
Let's keep it until we'll find very strong reason for breaking it.

@lock
Copy link

lock bot commented Oct 28, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a [new issue] for related bugs.
If you feel like there's important points made in this discussion, please include those exceprts into that [new issue].
[new issue]: https://github.com/aio-libs/aiohttp/issues/new

@lock lock bot added the outdated label Oct 28, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 28, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants