Restfunc — A new approach to API rest. TL;DR

Sometimes we want to build an API rest that really helps us by making shorter, cleaner and more understandable requests or URLs. Even, we want coworkers to don’t pain when making complex requests or calls to the back-end, at filtering queries or doing some special sorting at any fields. That’s why I created this new API rest standard that accepts many possibilities focusing in functions as any programming language does. I tried to base this function orientation on Python manner to write and call built-in functions like len(), str(), int(), etc. So, let’s get started.

Versioning

First, the API rest design, which contains Authentication with web tokens using headers and all that staff, also contains a special care of versioning.

http://example.com/rest/api/v1/
http://example.com/rest/api/v2.0/

Or if you want to pass it as query parameter

http://example.com/rest/api/some?v=3.2.1

Even if you prefer to use the Hypermedia way

Accept: application/vnd.example.rest.api+xml; version=1.0

Asking resources

As we already know, we can use HTTP verbs to access to resources in any kind of method.

  • GET /products - Returns the list of products
  • GET /products/12 - Returns the products with id 12
  • POST /products - Creates a new product
  • PUT /products/12 - Updates the product with id 12
  • DELETE /products/12 —Deletes the product with id 12

Furthermore, resources can have relationships between them, so you can represent that relation on URL if it’s needed. For example, you want to get the list of products related with the user who has the id 12…

GET /users/12/products

The same way if you need any other HTTP verb

POST /users/12/products
PUT /users/12/products/15
DELETE /users/12/products/15

Examples so far

http://example.com/rest/api/events/1/attendances
http://example.com/rest/api/tickets/13?v=1.1.1
http://example.com/rest/api/v1/rooms/40/guests/3/relatives/2/dogs

Handling errors

At any error, an standard response will be returned which contains the reasons that made it and the HTTP status code will be included.


Filtering, sorting and selecting fields

This is the part that gets more important when you work collaborative and perhaps coworkers can figure out the query because of the simplicity and they don’t have to be reading over and over the API docs.

Filtering

This way is how you know the query parameters working well in a basic API.

~ /users/12/products?status=good&color=red

But what if you need to escape some blank spaces or special characters. You can use a simple function that takes all that as a string. You must use the function string() or the short way str().

~ /users/12/products?status=string(super good)&color=str(black-red)

String function ignores case sensitive by default, but if you want to change it, just send a second Boolean parameter in the function to don’t ignore it.

~ users/12/products?color=str(Dark blue, true)

You can use query parameters with any kind of value such as null, integers, string and booleans.

~ /users/12/products?stock_id=null&valid=true&count=2

Now, this is the list of functions and operators you can use for filtering. This is a very cool stuff, you can use comparators for dates like after, before, between, comparators for strings such as (like or contains), and much more, just take a look.

Also, you can create any other function you need

Sorting

This is a simple query parameter that makes your results get sorted by a specific field and increasing or decreasing using symbols (+) or (-) just before the name of the field.

/cars?sort=+color

Selecting fields

You can pick few fields of your query to avoid having some data you don’t need. To do that, just use a query parameter named fields with an array with the specific fields you need separated by comma, write fields in camel case o snake case and it will be understood

/cars?fields=(name, color, created_at, updatedAt)
# it returns:
[
{
"name": "car 1",
"color": "red",
"created_at": "2016-11-11",
"updated_at": "2016-11-20"
}
]

Queries with relationships between models

You can use the simple query parameter rel with an array of related models separated by comma and separate recursively relations by dot ( . ), like this

This asks for all products with their stocks, shops, and for every warehouse it has, ask for its owner.
/products?rel=(stocks, warehouses.owner, shops)

Reserved words and parameters

This list contains all the words and parameters we use as reserved to improve and make faster and readable your queries

Reserved words and query parameters can change depending on your API design

Advanced queries with RestSQL

RestSQL is a more advanced way to build and filter queries very similar to the WHERE clause in SQL. For this, you send a simple parameter named restsql with all the restrictions you want to apply, like this

/buses/1/drivers?restsql=(id in (1, 2, 3, 4, 5) or name like "cristhian" or (lower(last_name) = "leon" and phone not null))

These are the supported commands for RestSQL

Conclusion

This theory can be expanded and implemented as robust as needed, with any function we think is important for us. This restful design actually makes have a headache at the beginning, but once it’s implemented, all your projects can be easier, faster and more understandable. If you have comments or recommendations, just let me know it. Thanks for reading.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.