Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSON Parameters and Headers #3

Closed
wants to merge 7 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions draft/mson-parameters-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
---
RFC: XXXX
Author: Z
Status: Draft
Created: 2015-09-23
Last Modified: 2015-09-28
---

# API Blueprint RFC XXXX: MSON Parameters and Headers

## Table of Contents

- [Abstract](#abstract)
- [Motivation](#motivation)
- [Implementation](#implementation)
- [Backwards Compatibility](#backwards-compatibility)

## Abstract

This RFC proposes using full [MSON][] syntax for description of URI parameters
and HTTP headers.

## Motivation

Using MSON syntax for description of URI parameters and HTTP Headers will
greatly help to unify the API Blueprint syntax and introduce reusability of
URI parameters and HTTP headers. It will also greatly introduce the reusability
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be greatly improve instead of greatly introduce.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@geemus thanks I think my head was lost somewhere between the copy and paste 🙃 Any overall thoughts on this?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, copy/paste is one of my most prevalent errors for sure.

I still haven't played with MSON enough to have more specific feedback, but overall it seems really powerful/helpful to be able to do this. Being able to specify more about the headers/status is really lacking in pure json-schema (and previous to MSON it was harder to do params in blueprint). It seems like this could make both more accessible. Certainly look forward to seeing this land.

of other data structures.

In addition it will address many issues previously tracked on API Blueprint
GitHub repository.

### URI Parameters Issues Tracked

This RFC addresses following issues:

1. [Usage of data structures in Parameters](https://github.com/apiaryio/api-blueprint/issues/250)
1. [Global query URI parameter](https://github.com/apiaryio/api-blueprint/issues/24)
1. [Description of enumeration elements](https://github.com/apiaryio/api-blueprint/issues/119)
1. [Array in parameters](https://github.com/apiaryio/api-blueprint/issues/240)
1. [Minimum/Maximum values for URI Parameters](https://github.com/apiaryio/api-blueprint/issues/211)

NOTE: This is going to be addressed once MSON introduces validation.

### HTTP Headers Issues Tracked

This RFC addresses following issues:

1. [Parametric Headers Description](https://github.com/apiaryio/api-blueprint/issues/26)
1. [Referenced HTTP headers](https://github.com/apiaryio/api-blueprint/issues/17)
1. [Support for multiline syntax header](https://github.com/apiaryio/api-blueprint/issues/60)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would need to think about multiple headers with the same key (apiaryio/api-blueprint#345). Especially with how that will work with inheritance and mixins.

Example:

## Chapter [/TheBook/chapter{id}]
### View a chapter [GET]

+ Response 204
    + Headers
        + Include Pagination
        + Include Creatable

## Data Structures
### Pagination
+ Link (array)
    + `<http://example.com/TheBook/chapter1>; rel="prev"; title="previous chapter"`
    + `<http://example.com/TheBook/chapter3>; rel="next"; title="next chapter"`

### Creatable
+ Link: `<http://example.com/TheBook>; rel="create"; title="create a new chapter"`

The user would probably expect all three link headers to be present in the response, the pagination mixing and creatable mixin. Normally mixins in MSON would override the key names and only create link header would be present.


In addition this issue is solved by this RFC:

1. [Reuse headers and attributes](https://github.com/apiaryio/api-blueprint/issues/259)

## Implementation

### Parameters

The implementation should assume the existing syntax for API Blueprint
[URI parameters section][] is, in fact, an [MSON type declaration][].

The type being declared inherits from a *Parameters base type* unless specified
otherwise. If another base type is specified it must inherit from the
*Parameters base type*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this? Why can't we simply allow any arbitrary MSON data structure of base type object? They are still valid.

# Data Structures
## User (object)
+ name: pavan

# GET /users/{name}
+ Parameters (User)
+ Response 200 (application/json)
    + Attributes (User)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bear in mind I'm not very deeply knowledgeable (or experienced) in API Blueprint. That being said, It seems that requesting to inherit from a base parameter type means some for of multiple inheritance feature. It would introduce some possible type safety but in that case shouldn't there also be a Response base type and so on?

Given that it should already possible for users to create a Parameter base type if they want to, then maybe it's best to lower the barrier to entry and allow any arbitrary MSON data structure as @pksunkara suggests.


The *Parameter base type* may the [API Description Namespace][]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may the?

[`Href Variables`][] type.

The *Parameters base type* should be available as a type for use within any
[data structures section][].

#### Example

```apib
# Resource [/resource/{p}{?q}]
+ Parameters
+ p
+ q
```

Assuming `Parameters` as the name of the *Parameters base type*:

```apib
# Resource [/resource/{p}{?q}]
+ Parameters (My Parameters)

# Data Structures
## My Parameters (Parameters)
+ p
+ q
```

### Headers

The implementation of this RFC should introduce the use of MSON syntax in the
[Headers section][]. Similarly to Parameters section this Headers section should
be considered as [MSON type declaration][].

The type being declared inherits from a *Headers base type* unless specified
otherwise. If another base type is specified it must inherit from the
*Headers base type*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question to above. Do we need the Headers base type?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another argument against it is that it introduces a notion of global base types that are domain specific. They wouldn't fit in MSON, so you'd have to add them as a base type in maybe a MSON Apiary layer which seems like it would introduce a new moving part which makes the whole system just a little bit harder to understand (reading the MSON doc would not suffice to understand where the global base types come from).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To contradict this argument though. If there was a well understood transclusion mechanism (a la hercule using the HTTP reoslver - or the custom resolver work in progress) then having a library of "transcludable" well formed headers for various use cases would be a great community resource...


The *Headers base type* may the [API Description Namespace][] [`HTTP Headers`][]
type.

The *Headers base type* should be available as a type for use within any
[data structures section][].

### Example

```apib
# Resource [/resource]
## Retrieve [GET]
+ Response 200
+ Headers
+ Server: nginx
+ `X-RateLimit-Remaining`: 4987 (number) - Remaining rate limit
```

Assuming `Headers` as the name of the *Headers base type*:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't actually use the Headers as the name of the Headers base type in the below example.


```apib
# Resource [/resource]
## Retrieve [GET]
+ Response 200
+ Headers (My Headers)

# Data Structures
## My Headers
+ Server: nginx
+ `X-RateLimit-Remaining`: 4987 (number) - The rate limit remaining
```

## Considerations

### Parameters base type constraints

Using any type in as a member type in a descendant of Parameters base
type may lead into problems while representing its value in URL. The

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But isn't the question of the representation of the data structure in the the URL orthogonal from the definition of the data structure itself? That seems to touch on some of the discussion here:

For example, using commas, user_ids=1,2,3,4 instead of user_ids=1&user_ids=2&user_ids=3&user_ids=4

I guess that before abstracting that and making it pluggable, offering a couple of well specified serialisation formats should do the trick? For instance, Servant serialises arbitrary data types to a url parameter capture solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When it comes to arrays like you have in your example. URI Template already declares how this should be expanded based on the URI Template:

   .-----------------------------------------------------------------.
   | Level 4 examples, with variables having values of               |
   |                                                                 |
   |             list  := ("red", "green", "blue")                   |
   |             keys  := [("semi",";"),("dot","."),("comma",",")]   |
   |                                                                 |
   | Op       Expression            Expansion                        |
   |-----------------------------------------------------------------|
   |  ?  | Form-style query, ampersand-separated         (Sec 3.2.8) |
   |     |                                                           |
   |     |    {?list}               ?list=red,green,blue             |
   |     |    {?list*}              ?list=red&list=green&list=blue   |
   |     |    {?keys}               ?keys=semi,%3B,dot,.,comma,%2C   |
   |     |    {?keys*}              ?semi=%3B&dot=.&comma=%2C        |

RFC6570

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's about nested arrays? I.e. I have such structure

+ Comment
    + text: `hello world` (string, required)
    + tags (array[string], fixed-type)

and I want to describe resource which accepts comment

+# Resource [/resource{?comment}]
 +## Retrieve [GET]
  + Parameters(Comment)

How I can specify style of array in this situation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the objects and nested arrays serialisation is going to be complex and there is no set rules anywhere on how people do this. Each programming language & framework does it in it's own style

implementation should consider using `application/x-www-form-urlencoded`
together with [W3C HTML JSON form submission][] in the case where member type
is of structured type base.

Fore example:

```apib
# Resource [/resource{?q}]
+ Parameters
+ q (object)
+ member1: one
+ member2: two
```

Would result into:

```
/resource?q%5Bmember1%5D=one&p%5Bmember2%5D=two
```

Additionally, a parser implementation may consider producing a warning in
situations where member base type may cause an issue.

### Headers base type constraints

An implementation of a *Headers base type* descendant has to consider there may
be multiple headers of the same name (key) defined. Additionally, if a member
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to ask users to use an array if there are multiple headers for the same name (key).

# My Headers
+ Link (array)
    + first url
    + second url

type of an *Haders base type* descendant is of a structured type a certain form
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Headers

and parser warning should be considered similarly to Parameters base type.

### Interoperability with other Data Structures

It should be possible to use any MSON data structure – named type – as a member
type of Parameters or Headers-based type.

#### Example

```apib
# My Resource [/resource{?createdAfter}]
+ Attributes
+ created (Date) - Date when the resource was created

## Retrieve [GET]
+ Parameters
+ createdAfter (Date, optional) - Retrieve only resources created after this date

+ Response 200 (application/json)
+ Headers
+ Date (Date) - Date at which the message was originated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date is good since it's base type is string. But what about using a named type whose base type is an object?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And a named type whose base type is an list or an enum?

Copy link

@FranklinYu FranklinYu May 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pksunkara then I agree with the idea of "header base type", which restricts value to primitive types or array of them.


+ Attributes (My Resource)

# Data Structures

## Date (string)
Date as defined in ISO 8601.

### Sample
Tue, 15 Nov 1994 08:12:31 GMT
```

## Backwards Compatibility

Introducing MSON as syntax for URI Parameters and HTTP headers description must
be backward compatible with the existing syntax as it is.

[MSON]: https://github.com/apiaryio/mson
[URI parameters section]: https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-uriparameters-section
[Headers section]: https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-headers-section
[MSON type declaration]: https://github.com/apiaryio/mson/blob/master/MSON%20Specification.md#3-type-declaration
[API Description Namespace]: https://github.com/refractproject/refract-spec/blob/master/namespaces/api-description-namespace.md
[Href Variables]: https://github.com/refractproject/refract-spec/blob/master/namespaces/api-description-namespace.md#href-variables-object-type
[data structures section]: https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-data-structures
[W3C HTML JSON form submission]: http://www.w3.org/TR/html-json-forms/#the-application-json-encoding-algorithm
[HTTP Headers]: https://github.com/refractproject/refract-spec/blob/master/namespaces/api-description-namespace.md#http-headers-array-type