-
Notifications
You must be signed in to change notification settings - Fork 461
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
[WIP] Rewrite docs to include examples #115
Changes from 1 commit
4fd9d89
7a2ee42
71a5479
78c68f5
dff3225
66459b8
e888b47
9109dfa
d606d3b
7bf789b
4bd11a8
c0816fc
7177fa6
44efb84
0b707bb
60f743a
b255a5d
7548b6c
bf39868
e8cc934
9caf4c6
8964b4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,83 +15,94 @@ _**Micro —** Async ES6 HTTP microservices_ | |
* **Simple**. Oriented for single purpose modules (function). | ||
* **Explicit**. No middleware. Modules declare all dependencies. | ||
* **Standard**. Just HTTP! | ||
* **Lightweight**. The package is small and the `async` transpilation fast and transparent | ||
* **Lightweight**. The package is small and the `async` transpilation is fast and transparent | ||
|
||
## Example | ||
## How to use | ||
|
||
The following example `sleep.js` will wait before responding (without blocking!) | ||
Install it: | ||
|
||
```js | ||
const {send} = require('micro') | ||
const sleep = require('then-sleep') | ||
|
||
module.exports = async function (req, res) { | ||
await sleep(500) | ||
send(res, 200, 'Ready!') | ||
} | ||
``` | ||
npm install micro --save | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Command line indicator (dollar sign) missing. Also please put the flag before the package name! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done 🔥 |
||
``` | ||
|
||
To run the microservice on port `3000`, use the `micro` command: | ||
Add a script to your package.json like this: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done 🔥 |
||
|
||
```bash | ||
$ micro -p 3000 sleep.js | ||
``` | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing opening code fence (```) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 🙌 |
||
"main": "index.js", | ||
"scripts": { | ||
"start": "micro -p 3000" | ||
} | ||
} | ||
``` | ||
|
||
After that, we have to create an `index.js` file | ||
|
||
To run the microservice on port `3000` and localhost instead of listening on every interface, use the `micro` command: | ||
Populate `./index.js` inside your project: | ||
|
||
```bash | ||
$ micro -p 3000 -H localhost sleep.js | ||
```js | ||
module.exports = function (req, res) { | ||
return 'Welcome to micro' | ||
} | ||
``` | ||
|
||
## Usage | ||
and then just run `npm run start` and go to http://localhost:3000 | ||
|
||
**Note**: `micro` requires Node `6.0.0` or later | ||
So far, we have written a web server that sends 'Welcome to micro' | ||
|
||
Install the package: | ||
### Async / Await | ||
|
||
```js | ||
$ npm install --save micro | ||
``` | ||
<p><details> | ||
<summary><b>Examples</b></summary> | ||
<ul><li><a href="./examples/external-api">Fetch external api</a></li></ul> | ||
</details></p> | ||
|
||
And start using it in your `package.json` file: | ||
Micro is built for usage with async/await. You can read more about async / await [here](https://zeit.co/blog/async-and-await) | ||
|
||
```js | ||
"main": "index.js", | ||
"scripts": { | ||
"start": "micro -p 3000" | ||
const sleep = require('then-sleep') | ||
|
||
module.exports = async function (req, res) { | ||
await sleep(500) | ||
return 'Ready!' | ||
} | ||
``` | ||
|
||
Then write your `index.js` (see above for an example). To run your | ||
app and make it listen on `http://localhost:3000` run: | ||
#### Transpilation | ||
|
||
```bash | ||
$ npm start | ||
``` | ||
We use [is-async-supported](https://github.com/timneutkens/is-async-supported) combined with [async-to-gen](https://github.com/leebyron/async-to-gen), | ||
so that the we only convert `async` and `await` to generators when needed. | ||
|
||
### API | ||
If you want to do it manually, you can! `micro(1)` is idempotent and | ||
should not interfere. | ||
|
||
#### micro | ||
**`micro(fn)`** | ||
`micro` exclusively supports Node 6+ to avoid a big transpilation | ||
pipeline. `async-to-gen` is fast and can be distributed with | ||
the main `micro` package due to its small size. | ||
|
||
- This function is exposed as the `default` export. | ||
- Use `require('micro')`. | ||
- Returns a [`http.Server`](https://nodejs.org/dist/latest-v4.x/docs/api/http.html#http_class_http_server) that uses the provided `fn` as the request handler. | ||
- The supplied function is run with `await`. It can be `async`! | ||
- Example: | ||
|
||
```js | ||
const micro = require('micro'); | ||
const sleep = require('then-sleep'); | ||
const srv = micro(async function (req, res) { | ||
await sleep(500); | ||
res.writeHead(200); | ||
res.end('woot'); | ||
}); | ||
srv.listen(3000); | ||
``` | ||
|
||
#### json | ||
### Body parsing | ||
|
||
<p id="body-parsing-examples"><details> | ||
<summary><b>Examples</b></summary> | ||
<ul> | ||
<li><a href="./examples/json-parsing">Parse JSON</a></li> | ||
<li><a href="./examples/urlencoded-parsing">Parse urlencoded form (html `<form>`)</a></li> | ||
</ul> | ||
</details></p> | ||
|
||
For parsing the incoming request body we included an async function `json` | ||
|
||
```js | ||
const { json } = require('micro') | ||
|
||
module.exports = async function (req, res) { | ||
const data = await json(req) | ||
console.log(data.price) | ||
return '' | ||
} | ||
``` | ||
|
||
#### Api | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API (it's an abbreviation) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 🙌 |
||
|
||
**`json(req, { limit = '1mb' })`** | ||
|
||
|
@@ -100,18 +111,23 @@ $ npm start | |
- Exposes an `async` function that can be run with `await`. | ||
- `limit` is how much data is aggregated before parsing at max. Otherwise, an `Error` is thrown with `statusCode` set to `413` (see [Error Handling](#error-handling)). It can be a `Number` of bytes or [a string](https://www.npmjs.com/package/bytes) like `'1mb'`. | ||
- If JSON parsing fails, an `Error` is thrown with `statusCode` set to `400` (see [Error Handling](#error-handling)) | ||
- Example: | ||
|
||
```js | ||
const { json, send } = require('micro'); | ||
module.exports = async function (req, res) { | ||
const data = await json(req); | ||
console.log(data.price); | ||
send(res, 200); | ||
} | ||
``` | ||
|
||
#### send | ||
For other types of data check the [examples](#body-parsing-examples) | ||
|
||
### Sending a different status code | ||
|
||
So far we have used `return` to send data to the client. `return 'Hello World'` is the equivalent of `send(res, 200, 'Hello World')`. | ||
|
||
```js | ||
const { send } = require('micro') | ||
module.exports = async function (req, res) { | ||
const statusCode = 400 | ||
const data = { error: 'Custom error message' } | ||
send(res, statusCode, data) | ||
} | ||
``` | ||
|
||
#### Api | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API (it's an abbreviation) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 🙌 |
||
|
||
**`send(res, statusCode, data = null)`** | ||
|
||
|
@@ -123,62 +139,31 @@ $ npm start | |
- `object`: `data` is serialized as JSON. | ||
- `string`: `data` is written as-is. | ||
- If JSON serialization fails (for example, if a cyclical reference is found), a `400` error is thrown. See [Error Handling](#error-handling). | ||
- Example | ||
|
||
```js | ||
const { send } = require('micro') | ||
module.exports = async function (req, res) { | ||
send(res, 400, { error: 'Please use a valid email' }); | ||
} | ||
``` | ||
|
||
#### return | ||
|
||
**`return val;`** | ||
### Programmatic use | ||
|
||
- Returning `val` from your function is shorthand for: `send(res, 200, val)`. | ||
- Example | ||
|
||
```js | ||
module.exports = function (req, res) { | ||
return {message: 'Hello!'}; | ||
} | ||
``` | ||
|
||
- Returning a promise works as well! | ||
- Example | ||
|
||
```js | ||
const sleep = require('then-sleep') | ||
module.exports = async function (req, res) { | ||
return new Promise(async (resolve) => { | ||
await sleep(100); | ||
resolve('I Promised'); | ||
}); | ||
} | ||
``` | ||
You can use micro programmatically by requiring micro directly: | ||
|
||
#### sendError | ||
|
||
**`sendError(req, res, error)`** | ||
```js | ||
const micro = require('micro') | ||
const sleep = require('then-sleep') | ||
|
||
- Use `require('micro').sendError`. | ||
- Used as the default handler for errors thrown. | ||
- Automatically sets the status code of the response based on `error.statusCode`. | ||
- Sends the `error.message` as the body. | ||
- During development (when `NODE_ENV` is set to `'development'`), stacks are printed out with `console.error` and also sent in responses. | ||
- Usually, you don't need to invoke this method yourself, as you can use the [built-in error handling](#error-handling) flow with `throw`. | ||
const server = micro(async function (req, res) { | ||
await sleep(500) | ||
return 'Hello world' | ||
}) | ||
|
||
#### createError | ||
server.listen(3000) | ||
``` | ||
|
||
**`createError(code, msg, orig)`** | ||
#### Api | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API (it's an abbreviation) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 🙌 |
||
|
||
- Use `require('micro').createError`. | ||
- Creates an error object with a `statusCode`. | ||
- Useful for easily throwing errors with HTTP status codes, which are interpreted by the [built-in error handling](#error-handling). | ||
- `orig` sets `error.originalError` which identifies the original error (if any). | ||
**`micro(fn)`** | ||
|
||
<a name="error-handling"></a> | ||
- This function is exposed as the `default` export. | ||
- Use `require('micro')`. | ||
- Returns a [`http.Server`](https://nodejs.org/dist/latest-v6.x/docs/api/http.html#http_class_http_server) that uses the provided `function` as the request handler. | ||
- The supplied function is run with `await`. So it can be `async` | ||
|
||
### Error handling | ||
|
||
|
@@ -196,21 +181,21 @@ module.exports = async function (req, res) { | |
} | ||
``` | ||
|
||
If the API endpoint is abused, it can throw an error like so: | ||
If the API endpoint is abused, it can throw an error with ``createError`` like so: | ||
|
||
```js | ||
if (tooMany) { | ||
const err = new Error('Rate limit exceeded'); | ||
err.statusCode = 429; | ||
throw err; | ||
throw createError(429, 'Rate limit exceeded') | ||
} | ||
``` | ||
|
||
Alternatively you can use ``createError`` as described above. | ||
Alternatively you can create the `Error` object yourself | ||
|
||
```js | ||
if (tooMany) { | ||
throw createError(429, 'Rate limit exceeded') | ||
const err = new Error('Rate limit exceeded'); | ||
err.statusCode = 429; | ||
throw err; | ||
} | ||
``` | ||
|
||
|
@@ -234,6 +219,7 @@ If a generic error is caught, the status will be set to `500`. | |
In order to set up your own error handling mechanism, you can use composition in your handler: | ||
|
||
```js | ||
const { send } = require('micro') | ||
module.exports = handleErrors(async (req, res) => { | ||
throw new Error('What happened here?'); | ||
}); | ||
|
@@ -250,6 +236,24 @@ function handleErrors (fn) { | |
} | ||
``` | ||
|
||
#### Api | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. API (it's an abbreviation) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 🙌 |
||
|
||
**`sendError(req, res, error)`** | ||
|
||
- Use `require('micro').sendError`. | ||
- Used as the default handler for errors thrown. | ||
- Automatically sets the status code of the response based on `error.statusCode`. | ||
- Sends the `error.message` as the body. | ||
- During development (when `NODE_ENV` is set to `'development'`), stacks are printed out with `console.error` and also sent in responses. | ||
- Usually, you don't need to invoke this method yourself, as you can use the [built-in error handling](#error-handling) flow with `throw`. | ||
|
||
**`createError(code, msg, orig)`** | ||
|
||
- Use `require('micro').createError`. | ||
- Creates an error object with a `statusCode`. | ||
- Useful for easily throwing errors with HTTP status codes, which are interpreted by the [built-in error handling](#error-handling). | ||
- `orig` sets `error.originalError` which identifies the original error (if any). | ||
|
||
### Testing | ||
|
||
Micro makes tests compact and a pleasure to read and write. | ||
|
@@ -271,21 +275,9 @@ test('my endpoint', async t => { | |
}); | ||
``` | ||
|
||
Look at the [test-listen](https://github.com/zeit/test-listen) for a | ||
Look at [test-listen](https://github.com/zeit/test-listen) for a | ||
function that returns a URL with an ephemeral port every time it's called. | ||
|
||
### Transpilation | ||
|
||
We use [is-async-supported](https://github.com/timneutkens/is-async-supported) combined with [async-to-gen](https://github.com/leebyron/async-to-gen), | ||
so that the we only convert `async` and `await` to generators when needed. | ||
|
||
If you want to do it manually, you can! `micro(1)` is idempotent and | ||
should not interfere. | ||
|
||
`micro` exclusively supports Node 6+ to avoid a big transpilation | ||
pipeline. `async-to-gen` is fast and can be distributed with | ||
the main `micro` package due to its small size. | ||
|
||
### Deployment | ||
|
||
You can use the `micro` CLI for `npm start`: | ||
|
@@ -314,4 +306,4 @@ Then simply run `npm start`! | |
|
||
## Credits | ||
|
||
Thanks Tom Yandell and Richard Hodgson for donating the `micro` npm name. | ||
Thanks Tom Yandell and Richard Hodgson for donating the `micro` npm name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 🔥