You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+166-5Lines changed: 166 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,50 @@ Lambda API has **ZERO** dependencies.
37
37
38
38
Lambda API was written to be extremely lightweight and built specifically for serverless applications using AWS Lambda. It provides support for API routing, serving up HTML pages, issuing redirects, serving binary files and much more. It has a powerful middleware and error handling system, allowing you to implement everything from custom authentication to complex logging systems. Best of all, it was designed to work with Lambda's Proxy Integration, automatically handling all the interaction with API Gateway for you. It parses **REQUESTS** and formats **RESPONSES** for you, allowing you to focus on your application's core functionality, instead of fiddling with inputs and outputs.
39
39
40
+
## Table of Contents
41
+
-[Installation](#installation)
42
+
-[Requirements](#requirements)
43
+
-[Configuration](#configuration)
44
+
-[Recent Updates](#recent-updates)
45
+
-[Routes and HTTP Methods](#routes-and-http-methods)
For detailed release notes see [Releases](https://github.com/jeremydaly/lambda-api/releases).
67
111
112
+
### v0.6: Support for both `callback-style` and `async-await`
113
+
In additional to `res.send()`, you can now simply `return` the body from your route and middleware functions. See [Returning Responses](#returning-responses) for more information.
114
+
68
115
### v0.5: Remove Bluebird Promises Dependency
69
116
Now that AWS Lambda supports Node v8.10, asynchronous operations can be handled more efficiently with `async/await` rather than with promises. The core Lambda API execution engine has been rewritten to take advantage of `async/await`, which means we no longer need to depend on Bluebird. We now have **ZERO** dependencies.
Routes are defined by using convenience methods or the `METHOD` method. There are currently six convenience route methods: `get()`, `post()`, `put()`, `patch()`, `delete()` and`options()`. Convenience route methods require two parameters, a *route* and a function that accepts two arguments. A *route* is simply a path such as `/users`. The second parameter must be a function that accepts a `REQUEST` and a `RESPONSE` argument. These arguments can be named whatever you like, but convention dictates `req` and `res`. Examples using convenience route methods:
138
+
Routes are defined by using convenience methods or the `METHOD` method. There are currently eight convenience route methods: `get()`, `post()`, `put()`, `patch()`, `delete()`, `head()`,`options()` and `any()`. Convenience route methods require two parameters, a *route* and a function that accepts two arguments. A *route* is simply a path such as `/users`. The second parameter must be a function that accepts a `REQUEST` and a `RESPONSE` argument. These arguments can be named whatever you like, but convention dictates `req` and `res`. Examples using convenience route methods:
Additional methods are support by calling the `METHOD` method with three arguments. The first argument is the HTTP method, a *route*, and a function that accepts a `REQUEST` and a `RESPONSE` argument.
153
+
Additional methods are support by calling the `METHOD` method with three arguments. The first argument is the HTTP method (or array of methods), a *route*, and a function that accepts a `REQUEST` and a `RESPONSE` argument.
All `GET` methods have a `HEAD` alias that executes the `GET` request but returns a blank `body`. `GET` requests should be idempotent with no side effects. The `head()` convenience method can be used to set specific paths for `HEAD` requests or to override default `GET` aliasing.
166
+
167
+
Routes that use the `any()` method or pass `ANY` to `api.METHOD` will respond to all HTTP methods. Routes that specify a specific method (such as `GET` or `POST`), will override the route for that method. For example:
A `POST` to `/users` will return "any", but a `GET` request would return "get". Please note that routes defined with an `ANY` method will override default `HEAD` aliasing for `GET` routes.
175
+
176
+
## Returning Responses
177
+
178
+
Lambda API supports both `callback-style` and `async-await` for returning responses to users. The [RESPONSE](#response) object has several callbacks that will trigger a response (`send()`, `json()`, `html()`, etc.) You can use any of these callbacks from within route functions and middleware to send the response:
179
+
180
+
```javascript
181
+
api.get('/users', (req,res) => {
182
+
res.send({ foo:'bar' })
183
+
})
184
+
```
185
+
186
+
You can also `return` data from route functions and middleware. The contents will be sent as the body:
187
+
188
+
```javascript
189
+
api.get('/users', (req,res) => {
190
+
return { foo:'bar' }
191
+
})
192
+
```
193
+
194
+
### Async/Await
195
+
196
+
If you prefer to use `async/await`, you can easily apply this to your route functions.
197
+
198
+
Using `return`:
199
+
```javascript
200
+
api.get('/users', async (req,res) => {
201
+
let users =awaitgetUsers()
202
+
return users
203
+
})
204
+
```
205
+
206
+
Or using callbacks:
207
+
```javascript
208
+
api.get('/users', async (req,res) => {
209
+
let users =awaitgetUsers()
210
+
res.send(users)
211
+
})
212
+
```
213
+
214
+
### Promises
215
+
216
+
If you like promises, you can either use a callback like `res.send()` at the end of your promise chain, or you can simply `return` the resolved promise:
217
+
218
+
```javascript
219
+
api.get('/users', (req,res) => {
220
+
getUsers().then(users=> {
221
+
res.send(users)
222
+
})
111
223
})
112
224
```
113
225
114
-
All `GET` methods have a `HEAD` alias that executes the `GET` request but returns a blank `body`. `GET` requests should be idempotent with no side effects.
226
+
OR
227
+
228
+
```javascript
229
+
api.get('/users', (req,res) => {
230
+
returngetUsers().then(users=> {
231
+
return users
232
+
})
233
+
})
234
+
```
235
+
236
+
**IMPORTANT:** You must either use a callback like `res.send()`**OR**`return` a value. Otherwise the execution will hang and no data will be sent to the user. Also, be sure not to return `undefined`, otherwise it will assume no response.
This would create a `/v1/product` and `/v1/v2/product` route. You can also use `register()` to load routes from an external file without the `prefix`. This will just add routes to your `base` path. **NOTE:** Prefixed routes are built off of your `base` path if one is set. If your `base` was set to `/api`, then the first example above would produce the routes: `/api/v1/product` and `/api/v2/product`.
160
282
283
+
## Debugging Routes
284
+
285
+
Lambda API has a `routes()` method that can be called on the main instance that will return an array containing the `METHOD` and full `PATH` of every configured route. This will include base paths and prefixed routes. This is helpful for debugging your routes.
You can also log the paths in table form to the console by passing in `true` as the only parameter.
297
+
298
+
```javascript
299
+
constapi=require('lambda-api')()
300
+
301
+
api.get('/', (req,res) => {})
302
+
api.post('/test', (req,res) => {})
303
+
304
+
api.routes(true)
305
+
306
+
// Outputs to console
307
+
╔═══════════╤═════════════════╗
308
+
║ METHOD │ ROUTE ║
309
+
╟───────────┼─────────────────╢
310
+
║ GET │ / ║
311
+
╟───────────┼─────────────────╢
312
+
║ POST │ /test ║
313
+
╚═══════════╧═════════════════╝
314
+
```
315
+
161
316
162
317
## REQUEST
163
318
@@ -178,6 +333,7 @@ The `REQUEST` object contains a parsed and normalized request from API Gateway.
178
333
-`rawBody`: If the `isBase64Encoded` flag is `true`, this is a copy of the original, base64 encoded body
179
334
-`route`: The matched route of the request
180
335
-`requestContext`: The `requestContext` passed from the API Gateway
336
+
-`auth`: An object containing the `type` and `value` of an authorization header. Currently supports `Bearer`, `Basic`, `OAuth`, and `Digest` schemas. For the `Basic` schema, the object is extended with additional fields for username/password. For the `OAuth` schema, the object is extended with key/value pairs of the supplied OAuth 1.0 values.
181
337
-`namespace` or `ns`: A reference to modules added to the app's namespace (see [namespaces](#namespaces))
182
338
-`cookies`: An object containing cookies sent from the browser (see the [cookie](#cookiename-value-options)`RESPONSE` method)
**NOTE:** The `clearCookie()` method only sets the header. A execution ending method like `send()`, `json()`, etc. must be called to send the response.
390
546
547
+
### etag([boolean])
548
+
Enables Etag generation for the response if at value of `true` is passed in. Lambda API will generate an Etag based on the body of the response and return the appropriate header. If the request contains an `If-No-Match` header that matches the generated Etag, a `304 Not Modified` response will be returned with a blank body.
549
+
391
550
### attachment([filename])
392
551
Sets the HTTP response `Content-Disposition` header field to "attachment". If a `filename` is provided, then the `Content-Type` is set based on the file extension using the `type()` method and the "filename=" parameter is added to the `Content-Disposition` header.
393
552
@@ -508,6 +667,8 @@ api.use((req,res,next) => {
508
667
509
668
The `next()` callback tells the system to continue executing. If this is not called then the system will hang and eventually timeout unless another request ending call such as `error` is called. You can define as many middleware functions as you want. They will execute serially and synchronously in the order in which they are defined.
510
669
670
+
**NOTE:** Middleware can use either callbacks like `res.send()` or `return` to trigger a response to the user. Please note that calling either one of these from within a middleware function will terminate execution and return the response immediately.
671
+
511
672
## Clean Up
512
673
The API has a built-in clean up method called 'finally()' that will execute after all middleware and routes have been completed, but before execution is complete. This can be used to close database connections or to perform other clean up functions. A clean up function can be defined using the `finally` method and requires a function with two parameters for the REQUEST and the RESPONSE as its only argument. For example:
The `next()` callback will cause the script to continue executing and eventually call the standard error handling function. You can short-circuit the default handler by calling a request ending method such as `send`, `html`, or `json`.
693
+
The `next()` callback will cause the script to continue executing and eventually call the standard error handling function. You can short-circuit the default handler by calling a request ending method such as `send`, `html`, or `json` OR by `return`ing data from your handler.
533
694
534
695
## Namespaces
535
696
Lambda API allows you to map specific modules to namespaces that can be accessed from the `REQUEST` object. This is helpful when using the pattern in which you create a module that exports middleware, error, or route functions. In the example below, the `data` namespace is added to the API and then accessed by reference within an included module.
0 commit comments