Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 170 lines (135 sloc) 8.536 kb
a822aa2 @caseysoftware Initial commit
authored
1
02841dc @caseysoftware converted to markdown
authored
2 Background
3 ----------------
da51553 @caseysoftware adding some explanation and documentation;
authored
4
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
5 This started as an attempt to make an API for web2project. It quickly spiraled into something else as I realized that I hate maintaining docs, especially on systems with a lot of extension points and/or add ons. So started playing with OPTIONS.
6
7 For context, OPTIONS is covered in RFC 2616 in Section 9.2:
8
9 > The OPTIONS method represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
10 >
11 > Responses to this method are not cacheable.
12
13 The full spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
14
02841dc @caseysoftware converted to markdown
authored
15 The premise
16 ----------------
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
17
18 The problem with an API is moving from a) knowing nothing to b) knowing what Resources are available to c) how to interact with those Resources and then finally to d) actually interacting with those Resources.
19
20 In general, we use documentation but unfortunately most API documentation sucks.. it's out of date, incomplete, or outright wrong. I believe this is because the documentation is often an afterthought and done in parallel but separately from the API itself. AKA... you open a browser and then your favorite editor and copy/paste/tweak to get started.
21
22 But in HATEOAS/hypermedia land, a Resource should be able to describe itself. Further, a Resource should be able to express what other Resource relates to it and how via URIs. And finally, if we consider OPTIONS (info above), a Resource could describe how to interact with itself.
23
24
25 For this proof of concept, I wrote a simple wrapper for my open source project (web2project) where you can begin at the root of the API with an OPTIONS request. It checks the configuration to see which modules (Resources) are available and returns their respective URIs.
26
27 From there, you can make an OPTIONS request against any of the Resources to get a representation of the actions available. At the moment, I include: index, create, delete, edit, filter/search, help, and view. Each of those actions defines its own URI pattern, the required http method, and both the required and optional parameters available.
28
29 *I defined things in terms of actions instead of http methods because goals, not implementations are key.*
30
31 From there, to create a given Resource, you set the required parameters and attempt to create it. If successful, it returns a 201 Created and the fully formed Resource (with the new URI). If the request failed, it returns a 400, the full resource you passed it, and the specific error messages from the validation step. Theoretically, you could "guess" on what is a good request and "learn" from your previous mistakes via these error messages.
32
33 In our case with web2project:
34 * the required/optional fields are determined by instantiating the object behind the scenes and attempting to validate it. By doing it this way, the validation errors themselves give us the fields.. we don't have to maintain a separate list or doc
35 * the inter-Resource relationships are defined by individual property names on the objects, so we can auto-resolve both parent and child resources relative to your requested resource
36
02841dc @caseysoftware converted to markdown
authored
37 Some Drawbacks
38 ----------------
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
39
40 - OPTIONS is not cacheable, which means that any consumer of this API will have to re-request the OPTIONS info upon every new (request? interaction?)
41 - A few people have referred to this as "glorified RPC"
42
02841dc @caseysoftware converted to markdown
authored
43 Benefits
44 ----------------
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
45
46 - All documentation is in-band with the API itself, it's difficult for them to drift apart
47 - All documentation becomes semi-machine readable completely on the fly
48 - Since we now know required/optional fields at runtime, we should be able to decorate our forms (visually and with client-side validation) for individual fields
49 - In the case of web2project, if you use our naming conventions for Add On modules, you get this API for free
50
02841dc @caseysoftware converted to markdown
authored
51 Longer term ideas
52 ----------------
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
53
54 Now that we have these primitives - index, create, delete, edit, filter/search, help, and view - I would like to come up with "recipes" to describe a user flow through common actions.
da51553 @caseysoftware adding some explanation and documentation;
authored
55
02841dc @caseysoftware converted to markdown
authored
56 TODO
57 ----------------
da51553 @caseysoftware adding some explanation and documentation;
authored
58
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
59 - Add more information to the provided fields to describe required datatypes, formats, and (possibly) add human-readable descriptions
6d0612c @caseysoftware updating notes
authored
60 - Provide a variety of output formats/media
61 - Make use of accept headers to determine output format
b78f6c2 @caseysoftware added a bunch of explanation and more detail
authored
62 - Support authentication (Basic auth for now)
63 - The required parameters of resources are also appearing in the optional list, that is incorrect
64 - On a 201 Created, the new URI should also be in a Location header instead of just in the Resource
fd18396 @caseysoftware more notes
authored
65 - Implement HAL for the link relations, etc - http://stateless.co/hal_specification.html
07f3f72 @caseysoftware notes
authored
66 - Implement Siren - https://github.com/kevinswiber/siren
6d0612c @caseysoftware updating notes
authored
67
02841dc @caseysoftware converted to markdown
authored
68 DONE
69 ----------------
6d0612c @caseysoftware updating notes
authored
70
71 - Figure out how to identify and include the super/sub-resources automatically
69ce31d @caseysoftware adding more comments
authored
72 - Catch undefined resources (aka ones that don't have classes to map to) before the E_Fatal and return a 400 or 404
73 - Better error handling all the way around
da51553 @caseysoftware adding some explanation and documentation;
authored
74
02841dc @caseysoftware converted to markdown
authored
75 Sample
76 ----------------
da51553 @caseysoftware adding some explanation and documentation;
authored
77
8ecd0d2 @caseysoftware added the pretty print bit so I can actually remember it later
authored
78 Results of: curl -X OPTIONS http://localhost/web2project-slim/projects | python -mjson.tool
f9dd2e3 @caseysoftware formatting tweaks, trying to get the layout right
authored
79 ```json
da51553 @caseysoftware adding some explanation and documentation;
authored
80 {
f18538d @caseysoftware updating docs
authored
81 "actions": {
82 "create": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
83 "href": "/web2project-slim/projects",
84 "method": "POST",
85 "optional": [
86 "project_company", "project_name", "project_short_name", "project_owner",
87 "project_url", "project_demo_url", "project_start_date", "project_end_date",
88 "project_actual_end_date", "project_status", "project_percent_complete",
89 "project_color_identifier", "project_description", "project_target_budget",
90 "project_actual_budget", "project_scheduled_hours", "project_worked_hours",
91 "project_task_count", "project_creator", "project_active",
92 "project_private", "project_priority", "project_type", "project_parent",
93 "project_location", "project_original_parent", "project_departments",
94 "project_contacts"
95 ],
96 "required": [
97 "project_name", "project_short_name", "project_company",
98 "project_owner", "project_creator", "project_priority",
99 "project_color_identifier", "project_type", "project_status"
100 ]
101 },
cf47991 @caseysoftware fixing formatting
authored
102
f18538d @caseysoftware updating docs
authored
103 "delete": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
104 "href": "/web2project-slim/projects:id",
105 "method": "DELETE",
106 "required": [
107 "project_id"
108 ]
109 },
cf47991 @caseysoftware fixing formatting
authored
110
f18538d @caseysoftware updating docs
authored
111 "edit": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
112 "href": "/web2project-slim/projects/:id",
113 "method": "PATCH",
114 "optional": [
115 "project_company", "project_name", "project_short_name", "project_owner",
116 "project_url", "project_demo_url", "project_start_date", "project_end_date",
117 "project_actual_end_date", "project_status", "project_percent_complete",
118 "project_color_identifier", "project_description", "project_target_budget",
119 "project_actual_budget", "project_scheduled_hours", "project_worked_hours",
120 "project_task_count", "project_creator", "project_active",
121 "project_private", "project_priority", "project_type", "project_parent",
122 "project_location", "project_original_parent", "project_departments",
123 "project_contacts"
124 ],
f18538d @caseysoftware updating docs
authored
125 "required": [
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
126 "project_id"
f18538d @caseysoftware updating docs
authored
127 ]
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
128 },
cf47991 @caseysoftware fixing formatting
authored
129
f18538d @caseysoftware updating docs
authored
130 "filter": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
131 "href": "/web2project-slim/projects",
132 "method": "GET",
133 "optional": [
134 "page",
135 "limit"
136 ]
137 },
cf47991 @caseysoftware fixing formatting
authored
138
f18538d @caseysoftware updating docs
authored
139 "help": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
140 "href": "/web2project-slim/projects",
f18538d @caseysoftware updating docs
authored
141 "method": "OPTIONS"
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
142 },
cf47991 @caseysoftware fixing formatting
authored
143
f18538d @caseysoftware updating docs
authored
144 "index": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
145 "href": "/web2project-slim/projects",
f18538d @caseysoftware updating docs
authored
146 "method": "GET"
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
147 },
cf47991 @caseysoftware fixing formatting
authored
148
f18538d @caseysoftware updating docs
authored
149 "search": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
150 "href": "/web2project-slim/projects",
151 "method": "GET",
152 "required": [
153 "search"
154 ]
155 },
cf47991 @caseysoftware fixing formatting
authored
156
f18538d @caseysoftware updating docs
authored
157 "view": {
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
158 "href": "/web2project-slim/projects/:id",
159 "method": "GET",
160 "required": [
161 "project_id"
162 ]
f18538d @caseysoftware updating docs
authored
163 }
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
164 },
cf47991 @caseysoftware fixing formatting
authored
165
a3c84e1 @caseysoftware updating the example to be a little more clear
authored
166 "resource_uri": "/projects",
167 "root_uri": "/web2project-slim",
168 "self": "/web2project-slim/projects"
169 }
f9dd2e3 @caseysoftware formatting tweaks, trying to get the layout right
authored
170 ```
Something went wrong with that request. Please try again.