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

fix: better handling of route return type #349

Merged
merged 2 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,46 @@ from robyn import jsonify

@app.post("/jsonify")
async def json(request):
print(request)
return jsonify({"hello": "world"})
```

## Format of the Response
Robyn supports several kind of Response for your routes

#### Dictionary
Robyn accepts dictionaries to build a response for the route:

```python
@app.post("/dictionary")
async def dictionary(request):
return {
"status_code": 200,
"body": "This is a regular response",
"type": "text",
"headers": {"Header": "header_value"},
}
Comment on lines +112 to +117
Copy link
Member

@sansyrox sansyrox Jan 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @AntoineRR ,

The return type of json should be

return {
        "status_code": 200,
        "body":  jsonify({"hello": "world"},
        "headers": {"Content-Type": "application/json"},
    }

or just

return jsonify({"hello": "world"})

It will be returning a Plain Text otherwise

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my bad you're right, I will change this :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sansyrox it should be ok now 🙂

```

#### Response object
Robyn provides a `Response` object to help you build a valid response.

```python
from robyn.robyn import Response

@app.get("/response")
async def response(request):
return Response(status_code=200, headers={}, body="OK")
```

#### Other types
Whenever you want to use an other type for your routes, the `str` method will be called on it and it will be stored in the body of the response. Here is an example that returns a string:

```python
@app.get("/")
async def hello(request):
return "Hello World"
```

## Global Headers
You can also add global headers for every request.

Expand Down
31 changes: 31 additions & 0 deletions integration_tests/base_routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from robyn import Robyn, serve_file, jsonify, WS, serve_html
from robyn.robyn import Response

from robyn.templating import JinjaTemplate

Expand Down Expand Up @@ -232,6 +233,36 @@ async def redirect_route(request):
return "This is the redirected route"


@app.get("/types/response")
def response_type(request):
return Response(status_code=200, headers={}, body="OK")


@app.get("/types/str")
def str_type(request):
return "OK"


@app.get("/types/int")
def int_type(request):
return 0


@app.get("/async/types/response")
async def async_response_type(request):
return Response(status_code=200, headers={}, body="OK")


@app.get("/async/types/str")
async def async_str_type(request):
return "OK"


@app.get("/async/types/int")
async def async_int_type(request):
return 0


@app.get("/file_download_sync")
def file_download_sync():
current_file_path = pathlib.Path(__file__).parent.resolve()
Expand Down
35 changes: 35 additions & 0 deletions integration_tests/test_get_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,38 @@ def test_const_request_headers(session):
assert "Header" in r.headers
assert r.headers["Header"] == "header_value"


def test_response_type(session):
r = requests.get(f"{BASE_URL}/types/response")
assert r.status_code == 200
assert r.text == "OK"


def test_str_type(session):
r = requests.get(f"{BASE_URL}/types/str")
assert r.status_code == 200
assert r.text == "OK"


def test_int_type(session):
r = requests.get(f"{BASE_URL}/types/int")
assert r.status_code == 200
assert r.text == "0"


def test_async_response_type(session):
r = requests.get(f"{BASE_URL}/async/types/response")
assert r.status_code == 200
assert r.text == "OK"


def test_async_str_type(session):
r = requests.get(f"{BASE_URL}/async/types/str")
assert r.status_code == 200
assert r.text == "OK"


def test_async_int_type(session):
r = requests.get(f"{BASE_URL}/async/types/int")
assert r.status_code == 200
assert r.text == "0"
5 changes: 3 additions & 2 deletions robyn/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def __init__(self) -> None:
self.routes = []

def _format_response(self, res):
# handle file handlers
response = {}
if type(res) == dict:
status_code = res.get("status_code", 200)
Expand All @@ -39,9 +38,11 @@ def _format_response(self, res):
file_path = res.get("file_path")
if file_path is not None:
response.set_file_path(file_path)
elif type(res) == Response:
response = res
else:
response = Response(
status_code=200, headers={"Content-Type": "text/plain"}, body=res
status_code=200, headers={"Content-Type": "text/plain"}, body=str(res)
)

return response
Expand Down