|
| 1 | +[back to `@octokit/rest`](.) |
| 2 | + |
| 3 | +# How it works |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +<!-- ①②③④⑤⑥⑦⑧⑨⑩ --> |
| 8 | + |
| 9 | +1. [Endpoint options ① - ④](#endpoint-options) |
| 10 | +2. [Transform endpoint to request options ⑥ - ⑦](#transform) |
| 11 | +3. [Sending a request & receiving a response ⑧ & ⑩](#request) |
| 12 | +4. [Hooks ⑤ & ⑨](#request) |
| 13 | + |
| 14 | +<a name="endpoint-options"></a> |
| 15 | +## Endpoint options (① - ④) |
| 16 | + |
| 17 | +`@octokit/rest` exposes a method for each [REST API endpoint](https://developer.github.com/v3/), for example `github.repos.getForOrg()` for [`GET /orgs/:org/repos`](https://developer.github.com/v3/repos/#list-organization-repositories). The methods are generated from the [lib/routes.json](lib/routes.json) file which defines the **② endpoint default options** `method`, `url` and in some cases `headers`. |
| 18 | + |
| 19 | +**② endpoint default options** are merged with **① global defaults**, which are based on [lib/endpoint/defaults.js](lib/endpoint/defaults.js) and the options that were passed into the `require('@octokit/rest')(options)` client setup. |
| 20 | + |
| 21 | +Both are merged with **③ user options** passed into the method. Altogether they result in **④ endpoint options**. |
| 22 | + |
| 23 | +**Example**: get all public repositories of the the [@octokit GitHub organization](https://github.com/octokit). |
| 24 | + |
| 25 | +```js |
| 26 | +github.repos.getForOrg({org: 'octokit', type: 'public'}) |
| 27 | +``` |
| 28 | + |
| 29 | +**④ endpoint options** will be |
| 30 | + |
| 31 | +<table> |
| 32 | + <thead> |
| 33 | + <tr> |
| 34 | + <th>Option</th> |
| 35 | + <th>Value</th> |
| 36 | + <th>Source</th> |
| 37 | + </tr> |
| 38 | + </thead> |
| 39 | + <tr> |
| 40 | + <td><strong>baseUrl</strong></td> |
| 41 | + <td><code>'https://api.github.com'</code></td> |
| 42 | + <td>① endpoint defaults</td> |
| 43 | + </tr> |
| 44 | + <tr> |
| 45 | + <td><strong>user-agent</strong> <em>(header)</em></td> |
| 46 | + <td><code>'octokit/rest.js v1.0.0'</code></td> |
| 47 | + <td>① global defaults</td> |
| 48 | + </tr> |
| 49 | + <tr> |
| 50 | + <td><strong>accept</strong> <em>(header)</em></td> |
| 51 | + <td><code>'application/vnd.github.v3+json'</code></td> |
| 52 | + <td>① global defaults</td> |
| 53 | + </tr> |
| 54 | + <tr> |
| 55 | + <td><strong>method</strong></td> |
| 56 | + <td><code>'GET'</code></td> |
| 57 | + <td>② endpoint defaults</td> |
| 58 | + </tr> |
| 59 | + <tr> |
| 60 | + <td><strong>url</strong></td> |
| 61 | + <td><code>'/orgs/:org/repos'</code></td> |
| 62 | + <td>② endpoint defaults</td> |
| 63 | + </tr> |
| 64 | + <tr> |
| 65 | + <td><strong>org</strong> <em>(URL variable)</em></td> |
| 66 | + <td><code>'octokit'</code></td> |
| 67 | + <td>③ user options</td> |
| 68 | + </tr> |
| 69 | + <tr> |
| 70 | + <td><strong>type</strong> <em>(endpoint parameter)</em></td> |
| 71 | + <td><code>'public'</code></td> |
| 72 | + <td>③ user options</td> |
| 73 | + </tr> |
| 74 | +</table> |
| 75 | + |
| 76 | +<a name="transform"></a> |
| 77 | +## Transform endpoint to request options (⑥ - ⑦) |
| 78 | + |
| 79 | +**④ Endpoint options** are **⑥ transformed** into **⑦ request options**. Most of the transform is happening in [lib/endpoint/index.js](lib/endpoint/index.js). |
| 80 | + |
| 81 | +For example, the endpoint options shown above would result in |
| 82 | + |
| 83 | +<table> |
| 84 | + <tr> |
| 85 | + <th align=left>method</th> |
| 86 | + <td><code>'GET'</code></td> |
| 87 | + </tr> |
| 88 | + <tr> |
| 89 | + <th align=left>url</th> |
| 90 | + <td> <code>'https://api.github.com/orgs/octokit/repos?type=public'</code></td> |
| 91 | + </tr> |
| 92 | + <tr> |
| 93 | + <th align=left>headers[user-agent]</th> |
| 94 | + <td> <code>'octokit/rest.js v1.0.0'</code></td> |
| 95 | + </tr> |
| 96 | + </tr> |
| 97 | + <tr> |
| 98 | + <th align=left>headers[accept]</th> |
| 99 | + <td> <code>'application/vnd.github.v3+json'</code></td> |
| 100 | + </tr> |
| 101 | +</table> |
| 102 | + |
| 103 | +<a name="request"></a> |
| 104 | +## Sending a request & receiving a response ⑧ & ⑩ |
| 105 | + |
| 106 | +Using **⑦ request options** a **⑧ request** is sent to the GitHub REST API. The **⑩ response** is returned to the user. |
| 107 | + |
| 108 | +Most of the request/response is happening in [lib/request/request.js](lib/request/request.js). It is currently using Node’s native [http](https://nodejs.org/api/http.html) & [https](https://nodejs.org/api/https.html) modules, but we will probably use a fetch polyfill in future for better browser compatibility & smaller bundle size. |
| 109 | + |
| 110 | +<a name="hooks"></a> |
| 111 | +## Hooks ⑤ & ⑨ |
| 112 | + |
| 113 | +Hooks are used internally to inject functionality like authentication. For example, the internal [authentication plugin](lib/plugins/authentication) is registering a request hook in [lib/plugins/authentication/index.js](lib/plugins/authentication/index.js). The method sets the `authorization` header based on authentication previously set using `github.authenticate()` before the **⑧ request**. |
| 114 | + |
| 115 | +Hooks will be used in future for request pagination, throttling and handling of rate limits. |
| 116 | + |
| 117 | +Hooks can be registered using `github.hook.{before|after}`: |
| 118 | + |
| 119 | +```js |
| 120 | +github.hook.before('request', (options) => {}) |
| 121 | +github.hook.after('request', (response, options) => {}) |
| 122 | +``` |
| 123 | + |
| 124 | +The callbacks can return a Promise for asynchronous execution. `options` can be changed in the `github.hook.before` callback before they are transformed **⑥ transformed**. The **⑩ response** can be changed in the `github.hook.after` callback before it is returned to the user. |
| 125 | + |
| 126 | +⚠️ The API is currently experimental and can change at any time. |
0 commit comments