Reputation: 621
I am using Flask to create a couple of very simple services. From outside testing (using HTTPie) parameters through querystring are getting to the service.
But if I am using something like.
data = {
'param1': 'somevalue1',
'param2': 'somevalue2'}
response = self.client.get(url_for("api.my-service", **data))
I can see the correct URI being created:
http://localhost:5000/api1.0/my-service?param1=somevalue1¶m2=somevalue2
when I breakpoint into the service:
request.args
is actually empty.
self.client
is created by calling app.test_client()
on my configured Flask application.
Anyone has any idea why anything after ?
is being thrown away or how to work around it while still using test_client
?
Upvotes: 21
Views: 21224
Reputation: 314
If you are trying any other HTTP Method other than GET
response = self.client.patch(url_for("api.my-service"), query_string=data,
data="{}")
data="{}"
or data=json.dumps({})
should be there, even if there is no content in the body. Otherwise, it results in BAD Request.
Upvotes: 1
Reputation: 12260
For me the solution was to use the client within with
statements:
with app.app_context():
with app.test_request_context():
with app.test_client() as client:
client.get(...)
instead of
client = app.test_client()
client.get(...)
I put the creation of the test client in a fixture, so that it is "automatically" created for each test method:
from my_back_end import MyBackEnd
sut = None
app = None
client = None
@pytest.fixture(autouse=True)
def before_each():
global sut, app, client
sut = MyBackEnd()
app = sut.create_application('frontEndPathMock')
with app.app_context():
with app.test_request_context():
with app.test_client() as client:
yield
Upvotes: 0
Reputation: 1839
I know this is an old post, but I ran into this too. There's an open issue about this in the flask github repository. It appears this is intended behavior. From a response in the issue thread:
mitsuhiko commented on Jul 24, 2013
That's currently intended behavior. The first parameter to the test client should be a relative url. If it's not, then the parameters are removed as it's treated as if it was url joined with the second. This works:
>>> from flask import Flask, request
>>> app = Flask(__name__)
>>> app.testing = True
>>> @app.route('/')
... def index():
... return request.url
...
>>> c = app.test_client()
>>> c.get('/?foo=bar').data
'http://localhost/?foo=bar'
One way to convert your absolute url into a relative url and keep the query string is to use urlparse:
from urlparse import urlparse
absolute_url = "http://someurl.com/path/to/endpoint?q=test"
parsed = urlparse(absolute_url)
path = parsed[2] or "/"
query = parsed[4]
relative_url = "{}?{}".format(path, query)
print relative_url
Upvotes: 2
Reputation: 621
I've just found out a workaround.
Make
data = {
'param1': 'somevalue1',
'param2': 'somevalue2'}
response = self.client.get(url_for("api.my-service", **data))
into this:
data = {
'param1': 'somevalue1',
'param2': 'somevalue2'}
response = self.client.get(url_for("api.my-service"), query_string = data)
This works but seems a bit unintuitive, and debugging there is a place where the provided query string in the URI is thrown away ....
But anyway this works for the moment.
Upvotes: 39