Fetching Resources

To follow along with the examples in this chapter, you'll need a Render account. Sign up for one at Render if you don't already have one - it's free for basic usage.

Server Setup

This section of the book is going to make extensive use of a simple web API server, the code of which is available on GitHub.

To get your own server running on Render:

  1. Fork the repository to your GitHub account

  2. Log into your Render dashboard

  3. Create a PostgreSQL Database:

    • In your Render dashboard, click "New +" and select "PostgreSQL"

    • Choose a name for your database (e.g., "web-store-db")

    • Select the Free plan

    • Click "Create Database"

    • Once created, copy the "External Database URL" from the database info page

  4. Click "New +" and select "Web Service"

  5. Connect your GitHub repository

  6. Choose a name for your service (this will be part of your URL)

  7. In the configuration section, set:

    • Language: Ruby
    • Branch: master
    • Build Command: bundle install && bundle exec rake setup_db
    • Start Command: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

  8. Select Free Tier

  9. Under Environment Variables, add:

    • Key: DATABASE_URL
    • Value: [Paste the External Database URL you copied]

  10. Click "Deploy Web Service"


Your API will be available at https://[your-service-name].onrender.com

When working through the examples in this section, remember to replace web-store.onrender.com with your Render app's hostname.

Fetching a Resource

Given a working example API server, basic interactions can be performed with a simple command in a terminal – just like they were against the weather API:

$ http GET https://web-store.onrender.com/v1/products/1
HTTP/1.1 200 OK
CF-Cache-Status: DYNAMIC
CF-Ray: 8e7be02abf0ee297-BEG
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Sun, 24 Nov 2024 19:41:19 GMT
Server: cloudflare
Transfer-Encoding: chunked
Vary: Origin, Accept-Encoding
alt-svc: h3=":443"; ma=86400
rndr-id: 91fb9b2a-d87b-4240
status: 200 OK
x-render-origin-server: Render

{
    "id": 1,
    "name": "Red Pen",
    "price": 100,
    "sku": "redp100"
}

The response should look fairly familiar, but let's go over a few important details:

  • The media type is application/json.
  • The status is 200 OK.
  • The body is in JSON format.

The JSON body of the response is a representation of a single resource on the server, which represents a single product. When deserialized into a programming environment, the response body will be a single object. This representation includes id, name, price, and sku properties. The properties id and price are numbers, and name and sku are strings.

What is a Resource?

A resource is the representation of some grouping of data. A resource can be anything an API user needs to interact with. Blog software might expose posts, sections, tags, and comments as resources in its API, and it might allow users to create or edit any of those resources. A bank's API might provide access to accounts and transactions but only allow viewing transactions.

Every resource in a web API must have a unique URL that can be used to identify and access it. In this case, the URL was https://web-store.onrender.com/v1/products/1, and this URL was for a single resource on the server.

The hostname for this URL is web-store.onrender.com. Everything after the hostname is considered to be the path, which for this resource is /v1/products/1. The first segment of the path, /v1/, indicates we will be accessing version 1 of this API. APIs can have multiple versions, just like any other software.

While this path identifies a single resource, some identify multiple resources as a group. Let's look at an example.

Fetching a Collection

The web store server comes with a few preloaded products: a variety of pens, each with unique ink color. To see all of these products, perform a GET request using the collection's path:

$ http GET https://web-store.onrender.com/v1/products
HTTP/1.1 200 OK
CF-Cache-Status: DYNAMIC
CF-Ray: 8e7be42259e1e28f-BEG
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json
Date: Sun, 24 Nov 2024 19:44:00 GMT
Server: cloudflare
Transfer-Encoding: chunked
Vary: Origin, Accept-Encoding
alt-svc: h3=":443"; ma=86400
rndr-id: 3ec1f685-47d2-4a78
status: 200 OK
x-render-origin-server: Render

[
    {
        "id": 1,
        "name": "Red Pen",
        "price": 100,
        "sku": "redp100"
    },
    {
        "id": 2,
        "name": "Blue Pen",
        "price": 100,
        "sku": "blup100"
    },
    {
        "id": 3,
        "name": "Black Pen",
        "price": 100,
        "sku": "blap100"
    }
]

This response is very similar to the previous one for a single resource:

  • The media type is application/json.
  • The status is 200 OK.
  • The body is in JSON format.

A closer look at the content of the response, however, shows that data for three products has been returned. The JSON body of this response is a representation of a collection resource. When deserialized in a programming environment, the body of the response will be an array containing 3 objects.

Elements and Collections

There are two types of resources involved in the use of RESTful APIs: elements and collections.

Elements are the representation of a single resource, such as the first request above. Operations that involve a single resource are done in the context of that resource, and will use that resource's path.

Collections represent a grouping of elements of the same type. It is common for collection and element resources to have a parent-child relationship, where the collection is the "parent" and an element is a "child", although this is not always the case. Here is what could be the path to a collection of blog posts:

/api/blog/posts

This path represents the collection of all blog posts. Compare to it the path to an individual post:

/api/blog/posts/1

Since a single blog post is one of the elements in the collection of all blog posts, the path to the post is the path to the collection plus an extra value to identify the specific element of the collection. In this case, that value is 1.

How to know if a URL is for a collection or an element?

There are a few ways to know what kind of resource a URL represents by looking closely at its path. Keep in mind that when in doubt, it is best to reference the API's official documentation. Sometimes there won't be documentation, though, and there are a few clues that can be a sign of what kind of resource a URL is for.

Signs a URL is for a collection:

  1. The path ends in a plural word, such as example.com/products
  2. The response body contains multiple elements

Signs a URL is for a single element:

  1. The path ends in a plural word, a slash, and then what could be an identifier (which could be numeric or alphabetic)
  2. The response body contains a single element

Summary

  • APIs provide access to single resources (elements) or groups of resources (collections).
  • The path for an element is usually the path for its collection, plus an identifier for that resource.