Skip to content

Commit

Permalink
Merge branch 'refs/heads/request-bodies' into request-bodies-new
Browse files Browse the repository at this point in the history
# Conflicts:
#	robyn/openapi.py
  • Loading branch information
VishnuSanal committed Aug 27, 2024
2 parents 32e8e03 + 8f5cfe3 commit 95f4165
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 80 deletions.
128 changes: 128 additions & 0 deletions docs_src/src/pages/documentation/api_reference/openapi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,134 @@ app.include_router(subrouter)

</CodeGroup>

## Other Specification Params

We support all the params mentioned in the latest OpenAPI specifications (https://swagger.io/specification/). See an example of using request body below.

<CodeGroup title="Request Body">

```python {{ title: 'untyped' }}
@dataclass
class Prop:
description: str
type: str


@dataclass
class PropObject:
prop_name: str
prop_body: Prop


@dataclass
class GetRequestSchema:
type: str
required: List[str]
properties: List[PropObject]

def __post_init__(self):
properties: dict = {}

for p in self.properties:
properties[p.prop_name] = p.prop_body

self.properties = properties


get_request_schema_object = GetRequestSchema(
type="object",
required=["status"],
properties=[
PropObject(
prop_name="name",
prop_body=Prop(description="Updated name of the pet", type="String"),
),
PropObject(
prop_name="status",
prop_body=Prop(description="Updated status of the pet", type="String"),
)
]
)


@app.get("/",
request_body=RequestBody(
description="hiii",
required=True,
content={
"application/x-www-form-urlencoded":
MediaType(
schema=get_request_schema_object
)
},
))
def read_root(r):
"""welcome!"""
return {"Hello": "World"}
```

```python {{ title: 'typed' }}
@dataclass
class Prop:
description: str
type: str


@dataclass
class PropObject:
prop_name: str
prop_body: Prop


@dataclass
class GetRequestSchema:
type: str
required: List[str]
properties: List[PropObject]

def __post_init__(self):
properties: dict = {}

for p in self.properties:
properties[p.prop_name] = p.prop_body

self.properties = properties


get_request_schema_object = GetRequestSchema(
type="object",
required=["status"],
properties=[
PropObject(
prop_name="name",
prop_body=Prop(description="Updated name of the pet", type="String"),
),
PropObject(
prop_name="status",
prop_body=Prop(description="Updated status of the pet", type="String"),
)
]
)


@app.get("/",
request_body=RequestBody(
description="hiii",
required=True,
content={
"application/x-www-form-urlencoded":
MediaType(
schema=get_request_schema_object
)
},
))
def read_root(r: Request) -> dict:
"""welcome!"""
return {"Hello": "World"}
```

</CodeGroup>

With the reference documentation deployed and running smoothly, Batman had a powerful new tool at his disposal. The Robyn framework had provided him with the flexibility, scalability, and performance needed to create an effective crime-fighting application, giving him a technological edge in his ongoing battle to protect Gotham City.


Expand Down
128 changes: 128 additions & 0 deletions docs_src/src/pages/documentation/example_app/openapi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,134 @@ app.include_router(subrouter)

</CodeGroup>

## Other Specification Params

We support all the params mentioned in the latest OpenAPI specifications (https://swagger.io/specification/). See an example of using request body below.

<CodeGroup title="Request Body">

```python {{ title: 'untyped' }}
@dataclass
class Prop:
description: str
type: str


@dataclass
class PropObject:
prop_name: str
prop_body: Prop


@dataclass
class GetRequestSchema:
type: str
required: List[str]
properties: List[PropObject]

def __post_init__(self):
properties: dict = {}

for p in self.properties:
properties[p.prop_name] = p.prop_body

self.properties = properties


get_request_schema_object = GetRequestSchema(
type="object",
required=["status"],
properties=[
PropObject(
prop_name="name",
prop_body=Prop(description="Updated name of the pet", type="String"),
),
PropObject(
prop_name="status",
prop_body=Prop(description="Updated status of the pet", type="String"),
)
]
)


@app.get("/",
request_body=RequestBody(
description="hiii",
required=True,
content={
"application/x-www-form-urlencoded":
MediaType(
schema=get_request_schema_object
)
},
))
def read_root(r):
"""welcome!"""
return {"Hello": "World"}
```

```python {{ title: 'typed' }}
@dataclass
class Prop:
description: str
type: str


@dataclass
class PropObject:
prop_name: str
prop_body: Prop


@dataclass
class GetRequestSchema:
type: str
required: List[str]
properties: List[PropObject]

def __post_init__(self):
properties: dict = {}

for p in self.properties:
properties[p.prop_name] = p.prop_body

self.properties = properties


get_request_schema_object = GetRequestSchema(
type="object",
required=["status"],
properties=[
PropObject(
prop_name="name",
prop_body=Prop(description="Updated name of the pet", type="String"),
),
PropObject(
prop_name="status",
prop_body=Prop(description="Updated status of the pet", type="String"),
)
]
)


@app.get("/",
request_body=RequestBody(
description="hiii",
required=True,
content={
"application/x-www-form-urlencoded":
MediaType(
schema=get_request_schema_object
)
},
))
def read_root(r: Request) -> dict:
"""welcome!"""
return {"Hello": "World"}
```

</CodeGroup>

With the reference documentation deployed and running smoothly, Batman had a powerful new tool at his disposal. The Robyn framework had provided him with the flexibility, scalability, and performance needed to create an effective crime-fighting application, giving him a technological edge in his ongoing battle to protect Gotham City.


Expand Down
60 changes: 56 additions & 4 deletions integration_tests/base_routes.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import os
import pathlib
from collections import defaultdict
from typing import Optional

from robyn import Headers
from dataclasses import dataclass
from typing import Optional, List

from integration_tests.subroutes import sub_router, di_subrouter
from integration_tests.views import SyncView, AsyncView
from robyn import Headers, RequestBody
from robyn import (
Request,
Response,
Expand All @@ -18,6 +18,7 @@
WebSocketConnector,
)
from robyn.authentication import AuthenticationHandler, BearerGetter, Identity
from robyn.openapi import MediaType
from robyn.templating import JinjaTemplate

app = Robyn(__file__)
Expand Down Expand Up @@ -834,7 +835,58 @@ def sync_router_di(request, router_dependencies):
return router_dependencies["ROUTER_DEPENDENCY"]


@app.get("/openapi_test", openapi_tags=["test tag"])
@dataclass
class Prop:
description: str
type: str


@dataclass
class PropObject:
prop_name: str
prop_body: Prop


@dataclass
class GetRequestSchema:
type: str
required: List[str]
properties: List[PropObject]

def __post_init__(self):
properties: dict = {}

for p in self.properties:
properties[p.prop_name] = p.prop_body

self.properties = properties


get_request_schema_object = GetRequestSchema(
type="object",
required=["status"],
properties=[
PropObject(
prop_name="name",
prop_body=Prop(description="Updated name of the pet", type="String"),
),
PropObject(
prop_name="status",
prop_body=Prop(description="Updated status of the pet", type="String"),
),
],
)


@app.get(
"/openapi_test",
openapi_tags=["test tag"],
request_body=RequestBody(
description="hii",
required=True,
content={"application/x-www-form-urlencoded": MediaType(schema=get_request_schema_object)},
),
)
def sample_openapi_endpoint():
"""Get openapi"""
return 200
Expand Down
17 changes: 17 additions & 0 deletions integration_tests/test_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,20 @@ def test_add_subrouter_paths():
assert route_type in openapi_spec["paths"][endpoint]
assert openapi_description == openapi_spec["paths"][endpoint][route_type]["description"]
assert openapi_tags == openapi_spec["paths"][endpoint][route_type]["tags"]


@pytest.mark.benchmark
def test_request_body():
openapi_spec = get("/openapi.json").json()

assert isinstance(openapi_spec, dict)

route_type = "get"
endpoint = "/openapi_test"
body_description = "hii"

assert endpoint in openapi_spec["paths"]
assert route_type in openapi_spec["paths"][endpoint]
assert "requestBody" in openapi_spec["paths"][endpoint][route_type]
assert "description" in openapi_spec["paths"][endpoint][route_type]["requestBody"]
assert body_description in openapi_spec["paths"][endpoint][route_type]["requestBody"]["description"]
Loading

0 comments on commit 95f4165

Please sign in to comment.