Quickstart¶
Decorators and function annotations indicate how a request will be handled.
Request Method¶
Uplink offers decorators that turn any method into a request definition. These
decorators provide the request method and relative URL of the intended
request: get
, post
,
put
, patch
and delete
.
The relative URL of the resource is specified in the decorator.
@get("users/list")
You can also specify query parameters in the URL.
@get("users/list?sort=desc")
Moreover, request methods must be bound to a Consumer
subclass.
class MyApi(Consumer):
@get("users/list")
def list_users(self):
"""List all users."""
URL Manipulation¶
A request URL can be updated dynamically using URI template parameters. A simple URI parameter is an
alphanumeric string surrounded by {
and }
.
To match the parameter with a method argument, either match the argument’s name with the alphanumeric string, like so
@get("group/{id}/users")
def group_list(self, id): pass
or use the Path
annotation.
@get("group/{id}/users")
def group_list(self, group_id: Path("id")): pass
Query
parameters can also be added.
@get("group/{id}/users")
def group_list(self, group_id: Path("id"), sort: Query): pass
For complex query parameter combinations, a mapping can be used:
@get("group/{id}/users")
def group_list(self, group_id: Path("id"), options: QueryMap): pass
Request Body¶
An argument’s value can be specified for use as an HTTP request body with the
Body
annotation:
@post("users/new")
def create_user(self, user: Body): pass
This annotation works well with the keyword arguments parameter (denoted by the ** prefix):
@post("users/new")
def create_user(self, **user_info: Body): pass
Form Encoded, Multipart, and JSON¶
Methods can also be declared to send form-encoded, multipart, and JSON data.
Form-encoded data is sent when form_url_encoded
decorates
the method. Each key-value pair is annotated with a Field
annotation:
@form_url_encoded
@post("user/edit")
def update_user(self, first_name: Field, last_name: Field): pass
Multipart requests are used when multipart
decorates the
method. Parts are declared using the Part
annotation:
@multipart
@put("user/photo")
def update_user(self, photo: Part, description: Part): pass
JSON data is sent when json
decorates the method. The
Body
annotation declares the JSON payload:
@uplink.json
@uplink.patch("/user")
def update_user(self, **user_info: uplink.Body):
"""Update an authenticated user."""
Header Manipulation¶
You can set static headers for a method using the headers
decorator.
@headers({
"Accept": "application/vnd.github.v3.full+json",
"User-Agent": "Uplink-Sample-App"
})
@get("users/{username}")
def get_user(self, username): pass
headers
can be used as a class decorator for headers that
need to be added to every request:
@headers({
"Accept": "application/vnd.github.v3.full+json",
"User-Agent": "Uplink-Sample-App"
})
class GitHub(Consumer):
...
A request header can be updated dynamically using the Header
function parameter annotation:
@get("user")
def get_user(self, authorization: Header):
"""Get an authenticated user."""
Synchronous vs. Asynchronous¶
By default, Uplink uses the Requests library to make requests. However, the
client
parameter of the Consumer
constructor offers a
way to swap out Requests with another HTTP client:
github = GitHub(BASE_URL, client=...)
Notably, Requests blocks while waiting for a response from a server.
For non-blocking requests, Uplink comes with optional support for
asyncio
and twisted
. Checkout this
example on GitHub
for more.
Deserializing the Response¶
The converter
parameter of the Consumer
constructor
accepts an adapter class that handles deserialization of HTTP response objects.
github = GitHub(BASE_URL, converter=...)
For instance, the MarshmallowConverter
adapter turns JSON
HTTP responses into Python objects using the marshmallow.Schema
object. Checkout this example on GitHub for more.