Skip to content

Commit

Permalink
feat: matching funciton returns value (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
Simone Sanfratello authored Oct 11, 2020
1 parent db4e2b6 commit 9598366
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 129 deletions.
34 changes: 20 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![NPM Downloads](https://img.shields.io/npm/dm/fastify-peekaboo.svg?style=flat)](https://www.npmjs.org/package/fastify-peekaboo)
[![JS Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
![100% code coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)
![Synk Security Rate](https://snyk-widget.herokuapp.com/badge/npm/fastify-peekaboo/1.3.0/badge.svg)
![Snyk Security Rate](https://snyk-widget.herokuapp.com/badge/npm/fastify-peekaboo/1.3.0/badge.svg)

fastify plugin for memoize responses by expressive settings.

Expand All @@ -30,9 +30,9 @@ Use arbitrary cache to serve responses from previous elaboration, matching them
- [Documentation](#documentation)
- [Changelog](#changelog)
- [Roadmap](#roadmap)
- [v. 2.1](#v-21)
- [v. 2.2](#v-22)
- [v. 2.3](#v-23)
- [v. 2.4](#v-24)
- [v. 2.5](#v-25)
- [License](#license)

## Installing
Expand Down Expand Up @@ -142,13 +142,13 @@ default: `memoize`
It set how the cache system behave:

- **memoize**
on each request, it check if there is the cache entry and serve that avoiding elaboration, or elaborate and cache
on each request, if the relative cache entry is present serve that, or elaborate and cache on response if it doesn't
- **collector**
only cache entries but don't use cache for serve responses
cache entries but don't use cache for serve responses
- **stock**
serve only responses from cache or 404 is the cache entry does not exists
serve only responses from cache or `404` if the cache entry does not exists
- **off**
the plugin is not used
the plugin is not used at all

You can get/set also at runtime by

Expand Down Expand Up @@ -225,11 +225,17 @@ See [documentation](./doc/README.md) for further information and examples.

## Changelog

- **v. 2.0.0** [ 2020-09-25 ] stable
- **v. 2.2.0** [ 2020-10-11 ]
- update matching `function` allow cache based on values, [see notes](./doc/README.md#match-by-function-notes)
- update documentation
- update deps

- **v. 2.0.0** [ 2020-09-25 ]
- add `dataset` feature
- update `mode` public methods

- **v. 1.3.0** [ 2020-07-25 ] stable
- **v. 1.3.0** [ 2020-07-25 ]
- stable version
- update to `fastify v3`
- update deps

Expand Down Expand Up @@ -264,26 +270,26 @@ See [documentation](./doc/README.md) for further information and examples.

## Roadmap

### v. 2.1
### v. 2.3

- [ ] remove `got` and use native http client
- [ ] remove `got` in favor of natvie `http` client
- [ ] `response.rewrite` option
- [ ] `request.rewrite` option
- [ ] postgresql storage
- [ ] redis storage

### v. 2.2
### v. 2.4

- [ ] doc: real world examples
- [ ] benchmark plugin overhead (autocannon?)
- [ ] benchmark with different storages
- [ ] on file upload?
- [ ] support binary request/response (upload, download)
- [ ] test edge cases
- [ ] querystring array or object
- [ ] preset recipes (example graphql caching)
- [ ] CI

### v. 2.3
### v. 2.5

- [ ] fine grained settings (storage, expiration, xheader ...) for each rule
- [ ] invalidate cache (by ...?)
Expand Down
232 changes: 141 additions & 91 deletions doc/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
**Index**

- [Matching system](#matching-system)
- [MatchRule](#matchrule)
- [MatchRequest](#matchrequest)
- [MatchResponse](#matchresponse)
- [MatchString](#matchstring)
- [MatchNumber](#matchnumber)
- [MatchList](#matchlist)
- [MatchObject](#matchobject)
- [Match by function notes](#match-by-function-notes)
- [Storage](#storage)
- [storage.get](#storageget)
- [storage.set](#storageset)
- [storage.rm](#storagerm)
- [storage.clear](#storageclear)
- [storage.list](#storagelist)
- [Dataset](#dataset)
- [dataset.get](#datasetget)
- [dataset.create](#datasetcreate)
- [dataset.update](#datasetupdate)
- [dataset.remove](#datasetremove)
- [dataset.set](#datasetset)
- [dataset.current](#datasetcurrent)
- [Examples](#examples)

---

## Matching system

#### MatchRule
### MatchRule

```js
{
Expand Down Expand Up @@ -157,7 +185,7 @@ use a function for more logic: anything but `DELETE`
request: { body: true }
```

match if body is present; also use the whole body for hashing
match if body is present; also use the whole body for caching

```js
request: { body: false }
Expand All @@ -173,7 +201,7 @@ response: {
}
```

match with a function, in this case only if `response` has no `authorization` header
match using a function, in this case only if `response` has no `authorization` header

```js
response: {
Expand All @@ -185,105 +213,36 @@ response: {
```

Match single object entries using a `MatchString` logic.
All entries must success in order to match the object.
All entries must succeed in order to match the object.
In this case, match all sent images less than 2k.

---

## Examples
### Match by function notes

Setup and run
In case the function returns `true`, the whole part is considered for caching;
if the function returns a value, the value is taken: in this way you can add a custom logic
for caching based on function evaluation.

```js
const fastify = require('fastify')
const peekaboo = require('fastify-peekaboo')
**Example**

const fastify = fastify()
fastify.register(peekaboo, {
rules: [
// list of matches, see below
]}
)
```js
response: {
body: (body) => {
return { user: body.userId }
}
}
```

- cache `GET /home` (using default settings)

```js
const rules = [{
request: {
methods: 'get',
route: '/home'
}
}]
```

- response using cache after from the second time, same response always
This is applied to matching `request.methods`, `request.route`, `request.headers`, `request.body`, `request.query`, but not on `MatchingObject` field functions.

```js
fastify.get('/home', async (request, response) => {
response.send('hey there')
})
```

- cache route /session by cookie

```js
const rules = [{
request: {
methods: '*',
route: '/session',
headers: {
cookie: true
}
}
}]
```

- response using cache but different from header/cookie, means that every request is based on cookie

```js
fastify.get('/session', async (request, response) => {
// cookie parsing is done by a plugin like fastify-cookie
// ... retrieve user
const _user = user.retrieve(request.cookies.token)
response.send('welcome ' + _user.name)
})
```

- cache route /content even if response is an error

```js
const rules = [{
request: {
methods: 'get',
route: /^\/content/,
},
response: {
headers: {
status: true
}
}
}]
```

- response using cache either on error too

```js
fastify.get('/content/:id', async (request, response) => {
const _id = parseInt(request.params.id)
if (isNaN(_id)) {
response.code(405).send('BAD_REQUEST')
return
}
response.send('your content ...')
})
```
---

## Storage

The storage allow access to entries for:

#### storage.get
### storage.get

retrieve the entry

Expand Down Expand Up @@ -322,7 +281,7 @@ fastify.get('/cache/get/:hash', async (request, response) => {
}
```

#### storage.set
### storage.set

set the content of a entry, all part must be provided:

Expand All @@ -341,7 +300,7 @@ fastify.put('/cache/set/:hash', async (request, response) => {
})
```

#### storage.rm
### storage.rm

```js
fastify.delete('/cache/rm/:hash', async (request, response) => {
Expand All @@ -350,7 +309,7 @@ fastify.delete('/cache/rm/:hash', async (request, response) => {
})
```

#### storage.clear
### storage.clear

```js
fastify.delete('/cache/clear', async (request, response) => {
Expand All @@ -359,7 +318,7 @@ fastify.delete('/cache/clear', async (request, response) => {
})
```

#### storage.list
### storage.list

retrieve the hashes of entries

Expand Down Expand Up @@ -455,3 +414,94 @@ fastify.get('/dataset/current', async (request, response) => {
response.send({current: fastify.peekaboo.dataset.current() })
})
```

---

## Examples

Setup and run

```js
const fastify = require('fastify')
const peekaboo = require('fastify-peekaboo')

const fastify = fastify()
fastify.register(peekaboo, {
rules: [
// list of matches, see below
]}
)
```

- cache `GET /home` (using default settings)

```js
const rules = [{
request: {
methods: 'get',
route: '/home'
}
}]
```

- response using cache after from the second time, same response always

```js
fastify.get('/home', async (request, response) => {
response.send('hey there')
})
```

- cache route /session by cookie

```js
const rules = [{
request: {
methods: '*',
route: '/session',
headers: {
cookie: true
}
}
}]
```

- response using cache but different from header/cookie, means that every request is based on cookie

```js
fastify.get('/session', async (request, response) => {
// cookie parsing is done by a plugin like fastify-cookie
// ... retrieve user
const _user = user.retrieve(request.cookies.token)
response.send('welcome ' + _user.name)
})
```

- cache route /content even if response is an error

```js
const rules = [{
request: {
methods: 'get',
route: /^\/content/,
},
response: {
headers: {
status: true
}
}
}]
```

- response using cache either on error too

```js
fastify.get('/content/:id', async (request, response) => {
const _id = parseInt(request.params.id)
if (isNaN(_id)) {
response.code(405).send('BAD_REQUEST')
return
}
response.send('your content ...')
})
```
Loading

0 comments on commit 9598366

Please sign in to comment.