apiaryio / api-blueprint

API Blueprint
https://apiblueprint.org
MIT License
8.64k stars 2.14k forks source link

Response with Headers and Model (Entity) #337

Closed Maykonn closed 5 years ago

Maykonn commented 8 years ago

I'm trying to specify a response:

+ Response 200 (application/json)

    [Account][]

    + Headers

            Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cLzU0LjI0My4xNC4zNVwvYWNjb3VudHNcL2xvZ2luIiwiaWF0IjoxNDY2NTIwOTYwLCJleHAiOjE0NjY1MjQ1NjAsIm5iZiI6MTQ2NjUyMDk2MCwianRpIjoiMmNmODAxZjU5ZDBkM2JhMDZiYWMyNmI2MDU4MGFkMDMifQ.6GFosBJkqG4PxHUUU7P56O2-JVARvMOM9vbBmx6-qTE
            X-RateLimit-Limit: 60
            X-RateLimit-Remaining: 55
            ETag: "3469b0c47f0dfdfa06a7fd887e97403f"
            Cache-Control: private, must-revalidate

My Model Account is:

## Account [/accounts/signup]

+ Model (application/json)

        {
          "id": 1,
          "username": "myusername",
          "email": "user@outlook.com",
          "fullname": "User FullName",
          "communication_status": "DISCONNECTED",
          "account_status": "ACTIVE",
          "photo": "http://photo_url_on_AWS_S3_static_bucket",
          "created_at": "2016-06-03 17:26:41",
          "updated_at": "2016-06-21 12:53:33"
        }

But response on documentation is wrong:

Response

    200

HEADERS
    server:Cowboy
    connection:keep-alive
    content-type:application/json
    authorization:Bearer eyaJ0eXiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cLzU0LjI0My4xNC4zNVawvYWNjb3VudHNcL2xvZ2luIiwiaWF0IjoxNDY2NTIwOTYwLCJleHAiOjE0NjY1MjQ1NjAsIm5iZiI6MTQNjUyMDk2MCwianRpIjoiMmNmODAxZjU5ZDBkM2JhMDZiYWMyNmI2MDU4MGFkMDMifQ.6GFosBJkqG4PxHUUU7P56O2-JVARvMOM9vbBmx6-qTE
    x-ratelimit-limit:60
    x-ratelimit-remaining:55
    etag:"3469b0c47f0dfdfa06a7fd887e97403f"
    cache-control:private, must-revalidate

// More headers here

The correct response must be headers and [Account][] data instead only headers. What happens?

kylef commented 5 years ago

When you have a Headers section inside a Response, then you will also need to move the response body into a body section otherwise it is a description block:

+ Response 200

    <description>

    + Headers

    + Body

    + Schema

    + Attributes

That's why when you add a headers section the [Account][] becomes a description and thus is rendered as such in Apiary documentation.

Moving the headers section into the model will work for this case, for example:

FORMAT: 1A

# Account API

## Account [/account]

+ Model (application/json)
    + Headers

            Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cLzU0LjI0My4xNC4zNVwvYWNjb3VudHNcL2xvZ2luIiwiaWF0IjoxNDY2NTIwOTYwLCJleHAiOjE0NjY1MjQ1NjAsIm5iZiI6MTQ2NjUyMDk2MCwianRpIjoiMmNmODAxZjU5ZDBkM2JhMDZiYWMyNmI2MDU4MGFkMDMifQ.6GFosBJkqG4PxHUUU7P56O2-JVARvMOM9vbBmx6-qTE
            X-RateLimit-Limit: 60
            X-RateLimit-Remaining: 55
            ETag: "3469b0c47f0dfdfa06a7fd887e97403f"
            Cache-Control: private, must-revalidate

    + Body

            {
                "id": 1,
                "username": "myusername",
                "email": "user@outlook.com",
                "fullname": "User FullName",
                "communication_status": "DISCONNECTED",
                "account_status": "ACTIVE",
                "photo": "http://photo_url_on_AWS_S3_static_bucket",
                "created_at": "2016-06-03 17:26:41",
                "updated_at": "2016-06-21 12:53:33"
            }

### View Account [GET]

+ Response 200

    [Account][]

However, I'd encourage you to move to MSON, which replaces the existing model system. This allows you to create a reusable data structure to represent the data without having to write JSON by hand. For example:

FORMAT: 1A

# Account API

## Account [/account]

+ Attributes
    + id: 1 (number)
    + username: myusername
    + email: user@outlook.com
    + fullname: User FullName
    + `communication_status` (enum)
        + DISCONNECTED
    + `account_status` (enum)
        + DISCONNECTED
    + photo: `http://photo_url_on_AWS_S3_static_bucket`
    + `created_at`: `2016-06-03 17:26:41`
    + `updated_at`: `2016-06-21 12:53:33`

### View Account [GET]

+ Response 200 (application/json)
    + Headers

            Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cLzU0LjI0My4xNC4zNVwvYWNjb3VudHNcL2xvZ2luIiwiaWF0IjoxNDY2NTIwOTYwLCJleHAiOjE0NjY1MjQ1NjAsIm5iZiI6MTQ2NjUyMDk2MCwianRpIjoiMmNmODAxZjU5ZDBkM2JhMDZiYWMyNmI2MDU4MGFkMDMifQ.6GFosBJkqG4PxHUUU7P56O2-JVARvMOM9vbBmx6-qTE
            X-RateLimit-Limit: 60
            X-RateLimit-Remaining: 55
            ETag: "3469b0c47f0dfdfa06a7fd887e97403f"
            Cache-Control: private, must-revalidate

    + Attributes (Account)

Some of the upsides is you can actually start describing these data structures with description values, you can also elaborate on the enumeration values such as the potential values that may be in communication_status. The rendered documentation will contain a table to show the structure:

screenshot 2019-01-11 at 17 53 31

Another upside, the API Blueprint parser will also generate both a JSON body and a JSON Schema for the same structure, for example:

{
  "id": 1,
  "username": "myusername",
  "email": "user@outlook.com",
  "fullname": "User FullName",
  "communication_status": "DISCONNECTED",
  "account_status": "DISCONNECTED",
  "photo": "http://photo_url_on_AWS_S3_static_bucket",
  "created_at": "2016-06-03 17:26:41",
  "updated_at": "2016-06-21 12:53:33"
}
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "id": {
      "type": "number"
    },
    "username": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "fullname": {
      "type": "string"
    },
    "communication_status": {
      "type": "string",
      "enum": [
        "DISCONNECTED"
      ]
    },
    "account_status": {
      "type": "string",
      "enum": [
        "DISCONNECTED"
      ]
    },
    "photo": {
      "type": "string"
    },
    "created_at": {
      "type": "string"
    },
    "updated_at": {
      "type": "string"
    }
  }
}