Skip to content

Commit

Permalink
fix SERVER_NAME enforcement in url_for and request.args documentation (
Browse files Browse the repository at this point in the history
…#1708)

* 🐛 fix SERVER_NAME enforcement in url_for

fixes #1707

* 💡 add additional documentation for using request.args

fixes #1704

* ✅ add additional test to check url_for without SERVER_NAME

* 📝 add changelog for fixes
  • Loading branch information
harshanarayana authored and yunstanford committed Nov 1, 2019
1 parent e506c89 commit e81a8ce
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 5 deletions.
3 changes: 3 additions & 0 deletions changelogs/1704.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix documentation for `get` and `getlist` of the `request.args`

Add additional example for showing the usage of `getlist` and fix the documentation string for `request.args` behavior
4 changes: 4 additions & 0 deletions changelogs/1707.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix `url_for` behavior with missing SERVER_NAME

If the `SERVER_NAME` was missing in the `app.config` entity, the `url_for` on the `request` and `app` were failing
due to an `AttributeError`. This fix makes the availability of `SERVER_NAME` on our `app.config` an optional behavior.
18 changes: 15 additions & 3 deletions docs/sanic/request_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,8 @@ The output will be:

## Accessing values using `get` and `getlist`

The request properties which return a dictionary actually return a subclass of
`dict` called `RequestParameters`. The key difference when using this object is
the distinction between the `get` and `getlist` methods.
The `request.args` returns a subclass of `dict` called `RequestParameters`.
The key difference when using this object is the distinction between the `get` and `getlist` methods.

- `get(key, default=None)` operates as normal, except that when the value of
the given key is a list, *only the first item is returned*.
Expand All @@ -223,6 +222,19 @@ args.get('titles') # => 'Post 1'
args.getlist('titles') # => ['Post 1', 'Post 2']
```

```python
from sanic import Sanic
from sanic.response import json

app = Sanic(name="example")

@app.route("/")
def get_handler(request):
return json({
"p1": request.args.getlist("p1")
})
```

## Accessing the handler name with the request.endpoint attribute

The `request.endpoint` attribute holds the handler's name. For instance, the below
Expand Down
7 changes: 5 additions & 2 deletions sanic/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,11 @@ def url_for(self, view_name, **kwargs):
:rtype: str
"""
# Full URL SERVER_NAME can only be handled in app.url_for
if "//" in self.app.config.SERVER_NAME:
return self.app.url_for(view_name, _external=True, **kwargs)
try:
if "//" in self.app.config.SERVER_NAME:
return self.app.url_for(view_name, _external=True, **kwargs)
except AttributeError:
pass

scheme = self.scheme
host = self.server_name
Expand Down
16 changes: 16 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2103,3 +2103,19 @@ async def bp_root(request):
request, response = await app.asgi_client.get("/bp")

assert request.endpoint == "named.my_blueprint.bp_root"


def test_url_for_without_server_name(app):
@app.route("/sample")
def sample(request):
return json({"url": request.url_for("url_for")})

@app.route("/url-for")
def url_for(request):
return text("url-for")

request, response = app.test_client.get("/sample")
assert (
response.json["url"]
== f"http://127.0.0.1:{app.test_client.port}/url-for"
)

0 comments on commit e81a8ce

Please sign in to comment.