1 | # cutie-rest
|
2 |
|
3 | [![NPM Version](https://img.shields.io/npm/v/@cuties/rest.svg)](https://npmjs.org/package/@cuties/rest)
|
4 | [![Build Status](https://travis-ci.org/Guseyn/cutie-rest.svg?branch=master)](https://travis-ci.org/Guseyn/cutie-rest)
|
5 | [![codecov](https://codecov.io/gh/Guseyn/cutie-rest/branch/master/graph/badge.svg)](https://codecov.io/gh/Guseyn/cutie-rest)
|
6 |
|
7 | [Cutie](https://github.com/Guseyn/cutie) extension for using REST (based on [cutie-http](https://github.com/Guseyn/cutie-http)) in Node. It's based on the [Async Tree Pattern](https://github.com/Guseyn/async-tree-patern/blob/master/Async_Tree_Patern.pdf).
|
8 |
|
9 | ## Install
|
10 |
|
11 | `npm install @cuties/https`
|
12 |
|
13 | ## Run test
|
14 |
|
15 | `npm test`
|
16 |
|
17 | ## Run build
|
18 |
|
19 | `npm run build`
|
20 |
|
21 | ## Run example
|
22 |
|
23 | `npm run example`
|
24 |
|
25 | ## Run procedural example
|
26 |
|
27 | `npm run procedural-example`
|
28 |
|
29 | ## Usage
|
30 |
|
31 | ```js
|
32 | const {
|
33 | // Needed async objects here from the table below
|
34 | } = require('@cuties/rest')
|
35 | ```
|
36 |
|
37 | This library provides following objects: `Backend, RestApi, RequestBody, CreatedServingFilesEndpoint, CreatedCachedServingFilesEndpoint, ServingFiles, CachedServingFiles` and `Endpoint, NotFoundEndpoint, IndexEndpoint, InternalServerErrorEndpoint` interfaces.
|
38 |
|
39 | | Object | Parameters(type) | Description |
|
40 | | ------ | -----------| ----------- |
|
41 | | `Backend` | `protocol, port(number), host(string), api(RestApi)[, options]`| It's `AsyncObject`. It Declares backend server with `protocol`(`http` or `https`) on specified `port` and `host`, also it provides declared `api` (REST). `options` is for options of the http/https server(it's optional).|
|
42 | | `RestApi` | `...endpoints`(classes that extend `Endpoint`) | Represents request-response listener. Declares endpoints of api. |
|
43 | | `RequestBody` | `request` | Reads body of `request` in `body(request, response)` method of `Endpoint` implementation |
|
44 | | `Endpoint` | `regexp(RegExp), method(string)[, ...args]` | Declares an endpoint(in api) with url that matches `regexp` and specified `method`('GET', 'POST', etc.). Also it's possible to pass some custom arguments via `...args`. This class has a method `body(request, response[, ...args])` that needs to be overridden and must return async object.|
|
45 | | `CreatedServingFilesEndpoint` | `regexp (RegExp or AsyncObject that represents RegExp), mapper (function(url) or AsyncObject that represents mapper function), notFoundEndpoint(Endpoint or AsyncObject that represents Endpoint)` | `AsyncObject` that represents `ServingFilesEndpoint` |
|
46 | | `CreatedCachedServingFilesEndpoint` | `regexp (RegExp or AsyncObject that represents RegExp), mapper (function(url) or AsyncObject that represents mapper function), notFoundEndpoint(Endpoint or AsyncObject that represents Endpoint)` | `AsyncObject` that represents `CachedServingFilesEndpoint` |
|
47 | | `ServingFilesEndpoint` | `regexp (RegExp), mapper (function(url)`), `notFoundEndpoint(Endpoint)` | Extends `Endpoint` and serves files on url that mathes `regexp` with `mapper` function that gets location of a file on a disk by the url. Also it's required to declare `notFoundEndpoint` that handles the cases when a file is not found. |
|
48 | | `CachedServingFilesEndpoint` | `regexp(RegExp), mapper(function(url)), notFoundEndpoint(Endpoint)` | Does the same that `ServingFilesEndpoint` does and caches files for increasing speed of serving them. |
|
49 | | `IndexEndpoint` | no args | `Endpoint` that is used for representing index page. |
|
50 | | `NotFoundEndpoint` | `regexp(RegExp)` | `Endpoint` that is used in `RestApi, ServingFilesEndpoint, CachedServingFilesEndpoint` for declaring endpoint on 404(NOT_FOUND) status. |
|
51 | | `InternalServerErrorEndpoint` | no args | `Endpoint` that is used for handling underlying internal failure(not for user error). |
|
52 |
|
53 | ## Example
|
54 |
|
55 | ```js
|
56 | 'use strict'
|
57 |
|
58 | const path = require('path')
|
59 | const {
|
60 | Backend,
|
61 | RestApi,
|
62 | CreatedServingFilesEndpoint,
|
63 | CreatedCachedServingFilesEndpoint
|
64 | } = require('@cuties/rest');
|
65 | const {
|
66 | CreatedOptions
|
67 | } = require('@cuties/https')
|
68 | const { ReadDataByPath } = require('@cuties/fs')
|
69 | const SimpleResponseOnGETRequest = require('./example/SimpleResponseOnGETRequest')
|
70 | const SimpleResponseOnPOSTRequest = require('./example/SimpleResponseOnPOSTRequest')
|
71 | const CustomNotFoundEndpoint = require('./example/CustomNotFoundEndpoint')
|
72 | const CustomInternalServerErrorEndpoint = require('./example/CustomInternalServerErrorEndpoint')
|
73 | const CustomIndexEndpoint = require('./example/CustomIndexEndpoint')
|
74 |
|
75 | const notFoundEndpoint = new CustomNotFoundEndpoint(new RegExp(/\/not-found/))
|
76 | const internalServerErrorEndpoint = new CustomInternalServerErrorEndpoint()
|
77 |
|
78 | const mapper = (url) => {
|
79 | let parts = url.split('/').filter(part => part !== '')
|
80 | return path.join(...parts)
|
81 | }
|
82 |
|
83 | const cacheMapper = (url) => {
|
84 | let parts = url.split('/').filter(part => part !== '').slice(1)
|
85 | parts.unshift('files')
|
86 | return path.join(...parts)
|
87 | }
|
88 |
|
89 | new Backend(
|
90 | 'https',
|
91 | 8000,
|
92 | '127.0.0.1',
|
93 | new RestApi(
|
94 | new CustomIndexEndpoint(),
|
95 | new SimpleResponseOnGETRequest(new RegExp(/^\/get/), 'GET'),
|
96 | new SimpleResponseOnPOSTRequest(new RegExp(/^\/post/), 'POST'),
|
97 | new CreatedServingFilesEndpoint(new RegExp(/^\/files/), mapper, notFoundEndpoint),
|
98 | new CreatedCachedServingFilesEndpoint(new RegExp(/^\/cached/), cacheMapper, notFoundEndpoint),
|
99 | notFoundEndpoint,
|
100 | internalServerErrorEndpoint
|
101 | ), new CreatedOptions(
|
102 | 'key', new ReadDataByPath('./example/pem/key.pem'),
|
103 | 'cert', new ReadDataByPath('./example/pem/cert.pem')
|
104 | )
|
105 | ).call()
|
106 |
|
107 |
|
108 | ```
|
109 |
|
110 | ## CustomIndexEndpoint
|
111 |
|
112 | ```js
|
113 | 'use strict'
|
114 |
|
115 | const { IndexEndpoint } = require('@cuties/rest')
|
116 |
|
117 | class CustomIndexEndpoint extends IndexEndpoint {
|
118 | constructor () {
|
119 | super()
|
120 | }
|
121 |
|
122 | body (request, response) {
|
123 | return super.body(request, response)
|
124 | }
|
125 | }
|
126 |
|
127 | module.exports = CustomIndexEndpoint
|
128 |
|
129 |
|
130 | ```
|
131 |
|
132 | [IndexEndpoint](https://github.com/Guseyn/cutie-rest/blob/master/src/backend/endpoint/IndexEndpoint.js)
|
133 |
|
134 | ## CustomNotFoundEndpoint
|
135 |
|
136 | ```js
|
137 | 'use strict'
|
138 |
|
139 | const { NotFoundEndpoint } = require('@cuties/rest')
|
140 |
|
141 | class CustomNotFoundEndpoint extends NotFoundEndpoint {
|
142 | constructor (regexpUrl) {
|
143 | super(regexpUrl)
|
144 | }
|
145 |
|
146 | body (request, response) {
|
147 | return super.body(request, response)
|
148 | }
|
149 | }
|
150 |
|
151 | module.exports = CustomNotFoundEndpoint
|
152 |
|
153 | ```
|
154 | [NotFoundEndpoint](https://github.com/Guseyn/cutie-rest/blob/master/src/backend/endpoint/NotFoundEndpoint.js)
|
155 |
|
156 | ## SimpleResponseOnGETRequest
|
157 |
|
158 | ```js
|
159 | 'use strict'
|
160 |
|
161 | const {
|
162 | Endpoint
|
163 | } = require('@cuties/rest')
|
164 | const {
|
165 | EndedResponse,
|
166 | WrittenResponse,
|
167 | ResponseWithWrittenHead
|
168 | } = require('@cuties/http')
|
169 |
|
170 | class SimpleResponseOnGETRequest extends Endpoint {
|
171 | constructor (regexpUrl, type) {
|
172 | super(regexpUrl, type)
|
173 | }
|
174 |
|
175 | body (request, response) {
|
176 | return new EndedResponse(
|
177 | new WrittenResponse(
|
178 | new ResponseWithWrittenHead(
|
179 | response, 200, 'ok', {
|
180 | 'Content-Type': 'text/plain'
|
181 | }
|
182 | ), 'content'
|
183 | ), ' is delivered'
|
184 | )
|
185 | }
|
186 | }
|
187 |
|
188 | module.exports = SimpleResponseOnGETRequest
|
189 |
|
190 | ```
|
191 |
|
192 | ## SimpleResponseOnPOSTRequest
|
193 |
|
194 | ```js
|
195 | 'use strict'
|
196 |
|
197 | const {
|
198 | EndedResponse,
|
199 | WrittenResponse,
|
200 | ResponseWithWrittenHead
|
201 | } = require('@cuties/http')
|
202 | const {
|
203 | Endpoint,
|
204 | RequestBody
|
205 | } = require('@cuties/rest')
|
206 |
|
207 | class SimpleResponseOnPOSTRequest extends Endpoint {
|
208 | constructor (regexpUrl, type) {
|
209 | super(regexpUrl, type)
|
210 | }
|
211 |
|
212 | body (request, response) {
|
213 | // request also contains body(as buffer), use RequestBody object for that
|
214 | return new EndedResponse(
|
215 | new WrittenResponse(
|
216 | new ResponseWithWrittenHead(
|
217 | response, 200, 'ok', {
|
218 | 'Content-Type': 'text/plain'
|
219 | }
|
220 | ), new RequestBody(request)
|
221 | ), ' is delivered'
|
222 | )
|
223 | }
|
224 | }
|
225 |
|
226 | module.exports = SimpleResponseOnPOSTRequest
|
227 |
|
228 | ```
|
229 |
|
230 | ## CustomInternalServerErrorEndpoint
|
231 |
|
232 | ```js
|
233 | 'use strict'
|
234 |
|
235 | const { InternalServerErrorEndpoint } = require('@cuties/rest')
|
236 |
|
237 | class CustomInternalServerErrorEndpoint extends InternalServerErrorEndpoint {
|
238 | constructor () {
|
239 | super()
|
240 | }
|
241 |
|
242 | body (request, response, error) {
|
243 | return super.body(request, response, error)
|
244 | }
|
245 | }
|
246 |
|
247 | module.exports = CustomInternalServerErrorEndpoint
|
248 |
|
249 | ```
|
250 | [InternalServerErrorMethod](https://github.com/Guseyn/cutie-rest/blob/master/src/backend/endpoint/InternalServerErrorEndpoint.js)
|