102 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			102 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | ||
|  | title: REST APIs with Falcon | ||
|  | --- | ||
|  | 
 | ||
|  | 
 | ||
|  | ## Introduction
 | ||
|  | 
 | ||
|  | RESTful APIs are a major component of any well-architected stack, and Python happens to have some brilliant frameworks for quickly composing APIs. One of these frameworks is called [Falcon](https://falconframework.org) - and it's great! Essentially a microframework, it ships with a sizable number of advantages: | ||
|  | 
 | ||
|  | 1. It's fast. Really fast. Check out the benchmarks [here](https://falconframework.org/#sectionBenchmarks). | ||
|  | 
 | ||
|  | 2. HTTP Resources are defined as classes, with class methods being used for different REST operations on these resources. This helps maintaining a clean codebase. | ||
|  | 
 | ||
|  | 3. It's quite extensible - check out [this section](https://github.com/falconry/falcon/wiki/Complementary-Packages) on their wiki, to get a feel for it.  | ||
|  | 
 | ||
|  | 4. It's based on WSGI - the Pythonic standard for web apps - so it works with Python 2.6, 2.7, and 3.3+. And if you need more performance, run it using PyPy! | ||
|  | 
 | ||
|  | 
 | ||
|  | ## Getting started
 | ||
|  | 
 | ||
|  | First, let's prepare our environment. Personally, it's always great to work in virtual environments - you can use `virtualenv`, `virtualenvwrapper` or `venv`. Next, install Falcon using `pip`: `pip install falcon`. | ||
|  | 
 | ||
|  | We're going to develop a small sample API that does very basic time-zone manipulations for us. It will display the current time in UTC, as well as the corresponding epoch time. To that end, we'll grab a nifty library called `arrow`: `pip install arrow`. | ||
|  | 
 | ||
|  | You can find the finished sample at [https://github.com/rudimk/freecodecamp-guides-rest-api-falcon](https://github.com/rudimk/freecodecamp-guides-rest-api-falcon). | ||
|  | 
 | ||
|  | ## Resources
 | ||
|  | 
 | ||
|  | Think of a resource as an entity that your API needs to manipulate. In our case, the best resource would be a `Timestamp`. Our routing would typically be something like this: | ||
|  | 
 | ||
|  | ``` | ||
|  | GET /timestamp | ||
|  | ``` | ||
|  | 
 | ||
|  | Here, `GET` is the HTTP verb used to call this endpoint, and `/timestamp` is the URL itself. Now that we've gotten this bit out of the way, let's create a module! | ||
|  | 
 | ||
|  | `$ touch timestamp.py` | ||
|  | 
 | ||
|  | Time to import the Falcon library: | ||
|  | 
 | ||
|  | ```python | ||
|  | 
 | ||
|  | import json | ||
|  | 
 | ||
|  | import falcon | ||
|  | 
 | ||
|  | import arrow | ||
|  | 
 | ||
|  | ``` | ||
|  | 
 | ||
|  | Note we've also import the `json` package and the `arrow` library. Now, let's define a class for our resource: | ||
|  | 
 | ||
|  | ```python | ||
|  | 
 | ||
|  | class Timestamp(object): | ||
|  | 
 | ||
|  | 	def on_get(self, req, resp): | ||
|  | 		payload = {} | ||
|  | 		payload['utc'] = arrow.utcnow().format('YYYY-MM-DD HH:mm:SS') | ||
|  | 		payload['unix'] = arrow.utcnow().timestamp | ||
|  | 
 | ||
|  | 		resp.body = json.dumps(payload) | ||
|  | 		resp.status = falcon.HTTP_200 | ||
|  | 
 | ||
|  | ``` | ||
|  | 
 | ||
|  | Let's go through this snippet. We've defined a `Timestamp` class, and defined a class method called `on_get` - this function tells Falcon that when a `GET` request is issued to an endpoint for this resource, run the `on_get` function and provide the request and response objects as parameters. After that, it's smooth sailing - we create an empty dictionary, fill it up with the current UTC and UNIX timestamps, convert it to JSON and attach it to the response object.  | ||
|  | 
 | ||
|  | Pretty simple, right? But sadly, that's not all. We now need to create a Falcon server and hook up the resource class we've just defined to an actual endpoint.  | ||
|  | 
 | ||
|  | `$ touch app.py` | ||
|  | 
 | ||
|  | Now, add the code below: | ||
|  | 
 | ||
|  | ```python | ||
|  | 
 | ||
|  | import falcon | ||
|  | 
 | ||
|  | from timestamp import Timestamp | ||
|  | 
 | ||
|  | api = application = falcon.API() | ||
|  | 
 | ||
|  | timestamp = Timestamp() | ||
|  | 
 | ||
|  | api.add_route('/timestamp', timestamp) | ||
|  | 
 | ||
|  | ``` | ||
|  | 
 | ||
|  | Here, we've defined a Falcon API, and initialized an instance of the resource class we created earlier. Then, we've hooked up the `/timestamp` endpoint with the class instance - and now we're good to go! To test this API install `gunicorn`(`pip install gunicorn`), and run `gunicorn app`. Use Postman or simple `cURL` to test this: | ||
|  | 
 | ||
|  | ``` | ||
|  | 
 | ||
|  | $ curl http://localhost:8000/timestamp                                                     | ||
|  | {"utc": "2017-10-20 06:03:14", "unix": 1508479437} | ||
|  | 
 | ||
|  | ``` | ||
|  | 
 | ||
|  | And that does it! | ||
|  | 
 | ||
|  | ## Moving on
 | ||
|  | 
 | ||
|  | Once you've got the hang of Falcon, composing powerful RESTful APIs that interact with databases or messaging queues is very easy. Do check out the [Falcon docs](https://falcon.readthedocs.io/en/stable/index.html), as well as PyPI for interesting Falcon modules that keep popping up. |