objective-http 1.2.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +71 -43
  2. package/package.json +1 -1
  3. package/src/js/bun/Bunttp.js +2 -5
  4. package/src/js/bun/client/index.js +2 -2
  5. package/src/js/bun/client/request/index.js +3 -0
  6. package/src/js/bun/client/response/index.js +3 -0
  7. package/src/js/bun/server/index.js +2 -2
  8. package/src/js/bun/server/request/InputRequest.js +5 -6
  9. package/src/js/bun/server/request/index.js +3 -0
  10. package/src/js/bun/server/response/OutputResponse.js +1 -25
  11. package/src/js/bun/server/response/index.js +3 -0
  12. package/src/js/client/index.js +2 -2
  13. package/src/js/client/request/OutputRequest.js +25 -41
  14. package/src/js/client/request/index.js +3 -0
  15. package/src/js/client/response/InputResponse.js +23 -21
  16. package/src/js/client/response/index.js +3 -0
  17. package/src/js/index.js +1 -5
  18. package/src/js/server/LoggedServer.js +6 -7
  19. package/src/js/server/Server.js +30 -26
  20. package/src/js/server/endpoint/Endpoint.js +7 -14
  21. package/src/js/server/endpoint/Endpoints.js +25 -15
  22. package/src/js/server/endpoint/index.js +4 -0
  23. package/src/js/server/index.js +3 -9
  24. package/src/js/server/request/InputRequest.js +23 -24
  25. package/src/js/server/request/LoggedInputRequest.js +13 -13
  26. package/src/js/server/request/index.js +4 -0
  27. package/src/js/server/response/LoggedOutputResponse.js +0 -4
  28. package/src/js/server/response/OutputResponse.js +1 -25
  29. package/src/js/server/response/index.js +4 -0
  30. package/src/js/server/endpoint/LoggedEndpoint.js +0 -30
  31. package/src/js/server/request/JsonInputRequest.js +0 -51
  32. package/src/js/server/response/JsonOutputResponse.js +0 -45
package/README.md CHANGED
@@ -13,27 +13,30 @@ const createServerFunction = require('node:http').createServer;
13
13
  const {
14
14
  Server,
15
15
  LoggedServer,
16
- InputRequest,
17
- JsonInputRequest,
18
- LoggedInputRequest,
19
- OutputResponse,
20
- JsonOutputResponse,
21
- LoggedOutputResponse,
22
- Endpoint,
23
- LoggedEndpoint,
24
- Endpoints
16
+ endpoint: {
17
+ Endpoint,
18
+ Endpoints
19
+ },
20
+ request: {
21
+ InputRequest,
22
+ LoggedInputRequest,
23
+ },
24
+ response: {
25
+ OutputResponse,
26
+ LoggedOutputResponse
27
+ }
25
28
  } = require('objective-http').server;
26
29
 
27
30
  new LoggedServer(
28
31
  new Server(
29
32
  new Endpoints([
30
- new MyFirstEndpoint(new LoggedEndpoint(new Endpoint(), console)),
31
- new MySecondEndpoint(new LoggedEndpoint(new Endpoint(), console)),
32
- new MyThirdEndpoint(new LoggedEndpoint(new Endpoint(), console))
33
+ new MyFirstEndpoint(),
34
+ new MySecondEndpoint(),
35
+ new MyThirdEndpoint()
33
36
  ]),
34
37
  {port: server_port},
35
- new LoggedInputRequest(new JsonInputRequest(new InputRequest()), console),
36
- new LoggedOutputResponse(new JsonOutputResponse(new OutputResponse()), console),
38
+ new LoggedInputRequest(new InputRequest(), console),
39
+ new LoggedOutputResponse(new OutputResponse(), console),
37
40
  createServerFunction
38
41
  ),
39
42
  console
@@ -77,8 +80,12 @@ class MyEndpoint {
77
80
  const requestFunction = require('node:http').request;
78
81
 
79
82
  const {
80
- OutputRequest,
81
- InputResponse
83
+ request: {
84
+ OutputRequest
85
+ },
86
+ response: {
87
+ InputResponse
88
+ }
82
89
  } = require('objective-http').client;
83
90
 
84
91
 
@@ -127,27 +134,30 @@ const createServerFunction = require('node:http').createServer;
127
134
  const {
128
135
  Server,
129
136
  LoggedServer,
130
- InputRequest,
131
- JsonInputRequest,
132
- LoggedInputRequest,
133
- OutputResponse,
134
- JsonOutputResponse,
135
- LoggedOutputResponse,
136
- Endpoint,
137
- LoggedEndpoint,
138
- Endpoints
137
+ endpoint: {
138
+ Endpoint,
139
+ Endpoints
140
+ },
141
+ request: {
142
+ InputRequest,
143
+ LoggedInputRequest,
144
+ },
145
+ response: {
146
+ OutputResponse,
147
+ LoggedOutputResponse
148
+ }
139
149
  } = require('objective-http').server;
140
150
 
141
151
  new LoggedServer(
142
152
  new Server(
143
153
  new Endpoints([
144
- new MyFirstEndpoint(new LoggedEndpoint(new Endpoint(), console)),
145
- new MySecondEndpoint(new LoggedEndpoint(new Endpoint(), console)),
146
- new MyThirdEndpoint(new LoggedEndpoint(new Endpoint(), console))
154
+ new MyFirstEndpoint(),
155
+ new MySecondEndpoint(),
156
+ new MyThirdEndpoint()
147
157
  ]),
148
158
  {port: server_port},
149
- new LoggedInputRequest(new JsonInputRequest(new InputRequest()), console),
150
- new LoggedOutputResponse(new JsonOutputResponse(new OutputResponse()), console),
159
+ new LoggedInputRequest(new InputRequest(), console),
160
+ new LoggedOutputResponse(new OutputResponse(), console),
151
161
  createServerFunction
152
162
  ),
153
163
  console
@@ -163,15 +173,25 @@ const createServerFunction = require('objective-http').bun.bunttp.createServer;
163
173
  const {
164
174
  Server,
165
175
  LoggedServer,
166
- InputRequest,
167
- JsonInputRequest,
168
- LoggedInputRequest,
169
- OutputResponse,
170
- JsonOutputResponse,
171
- LoggedOutputResponse,
172
- Endpoint,
173
- LoggedEndpoint,
174
- Endpoints
176
+ endpoint: {
177
+ Endpoint,
178
+ Endpoints
179
+ },
180
+ request: {
181
+ LoggedInputRequest,
182
+ },
183
+ response: {
184
+ LoggedOutputResponse
185
+ }
186
+ } = require('objective-http').server;
187
+
188
+ const {
189
+ request: {
190
+ InputRequest
191
+ },
192
+ response: {
193
+ OutputResponse
194
+ }
175
195
  } = require('objective-http').bun.server;
176
196
  ```
177
197
 
@@ -184,8 +204,12 @@ It should work with `node` and `bun`:
184
204
  const requestFunction = require('node:http').request;
185
205
 
186
206
  const {
187
- OutputRequest,
188
- InputResponse
207
+ request: {
208
+ OutputRequest
209
+ },
210
+ response: {
211
+ InputResponse
212
+ }
189
213
  } = require('objective-http').client;
190
214
 
191
215
  await (new OutputRequest(new InputResponse(), requestFunction)
@@ -203,7 +227,11 @@ In order for the code to be executed only by `bun`, you need to make changes to
203
227
  const requestFunction = require('objective-http').bun.bunttp.request;
204
228
 
205
229
  const {
206
- OutputRequest,
207
- InputResponse
230
+ request: {
231
+ OutputRequest
232
+ },
233
+ response: {
234
+ InputResponse
235
+ }
208
236
  } = require('objective-http').bun.client;
209
237
  ```
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"objective-http","version":"1.2.6","description":"Proxy classes for creating a http server","keywords":["web","web-server","http","http-server","oop"],"author":{"name":"volatilization","email":"volatilization@yandex.ru"},"repository":{"url":"git+https://github.com/volatilization/objective-http.git"},"license":"LGPL-3.0-only","main":"src/js/index.js"}
1
+ {"name":"objective-http","version":"1.4.0","description":"Proxy classes for creating a http server","keywords":["web","web-server","http","http-server","oop"],"author":{"name":"volatilization","email":"volatilization@yandex.ru"},"repository":{"url":"git+https://github.com/volatilization/objective-http.git"},"license":"LGPL-3.0-only","main":"src/js/index.js"}
@@ -12,16 +12,13 @@ module.exports = class Bunttp {
12
12
  }
13
13
 
14
14
  listen(options, cb) {
15
- const config = {...this.#serverConfig, port: options.port};
16
- const server = Bun.serve(config);
15
+ this.#server = Bun.serve({...this.#serverConfig, port: options.port});
17
16
  cb();
18
- return new Bunttp(config, server);
19
17
  }
20
18
 
21
19
  close(cb) {
22
- const server = this.#server.stop();
20
+ this.#server.stop();
23
21
  cb();
24
- return new Bunttp(this.#serverConfig, server);
25
22
  }
26
23
 
27
24
  request = fetch;
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
- OutputRequest: require('./request/OutputRequest'),
3
- InputResponse: require('./response/InputResponse')
2
+ request: require('./request'),
3
+ response: require('./response')
4
4
  }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ OutputRequest: require('./OutputRequest')
3
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ InputResponse: require('./InputResponse')
3
+ };
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
- InputRequest: require('./request/InputRequest'),
3
- OutputResponse: require('./response/OutputResponse')
2
+ request: require('./request'),
3
+ response: require('./response')
4
4
  }
@@ -16,8 +16,10 @@ module.exports = class InputRequest {
16
16
  return new InputRequest(
17
17
  this.#inputStream,
18
18
  {
19
- method: this.#inputStream.method,
20
- path: new URL(this.#inputStream.url).pathname,
19
+ route: {
20
+ method: this.#inputStream.method,
21
+ path: new URL(this.#inputStream.url).pathname
22
+ },
21
23
  query: new URL(this.#inputStream.url).searchParams,
22
24
  headers: this.#inputStream.headers,
23
25
  body: Buffer.from(await (await this.#inputStream.blob()).arrayBuffer())
@@ -30,10 +32,7 @@ module.exports = class InputRequest {
30
32
  }
31
33
 
32
34
  route() {
33
- return {
34
- method: this.#options.method.toString().toUpperCase(),
35
- path: this.#options.path.toString().toLowerCase()
36
- }
35
+ return this.#options.route;
37
36
  }
38
37
 
39
38
  query() {
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ InputRequest: require('./InputRequest')
3
+ };
@@ -7,14 +7,10 @@ module.exports = class OutputResponse {
7
7
  this.#outputStream = outputStream;
8
8
  }
9
9
 
10
- copy(options = this.#options, outputStream = this.#outputStream) {
10
+ copy(outputStream = this.#outputStream, options = this.#options) {
11
11
  return new OutputResponse({...{statusCode: 200, headers: {}}, ...options}, outputStream);
12
12
  }
13
13
 
14
- update(options) {
15
- return new OutputResponse(this.#mergeOptions(this.#options, options), this.#outputStream);
16
- }
17
-
18
14
  flush() {
19
15
  try {
20
16
  return new Response(this.#options.body, {
@@ -26,24 +22,4 @@ module.exports = class OutputResponse {
26
22
  throw new Error(e.message, {cause: 'INVALID_RESPONSE'});
27
23
  }
28
24
  }
29
-
30
- #mergeOptions(existedOptions, newOptions) {
31
- if (newOptions == null) {
32
- return existedOptions;
33
- }
34
-
35
- if (newOptions.statusCode != null) {
36
- existedOptions.statusCode = newOptions.statusCode;
37
- }
38
-
39
- if (newOptions.body != null) {
40
- existedOptions.body = newOptions.body;
41
- }
42
-
43
- if (newOptions.headers != null) {
44
- existedOptions.headers = {...existedOptions.headers, ...newOptions.headers};
45
- }
46
-
47
- return existedOptions;
48
- }
49
25
  }
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ OutputResponse: require('./OutputResponse')
3
+ };
@@ -1,4 +1,4 @@
1
1
  module.exports = {
2
- OutputRequest: require('./request/OutputRequest'),
3
- InputResponse: require('./response/InputResponse')
2
+ request: require('./request'),
3
+ response: require('./response')
4
4
  }
@@ -10,56 +10,40 @@ module.exports = class OutputRequest {
10
10
  }
11
11
 
12
12
  copy(options = this.#options, response = this.#response, http = this.#requestFunction) {
13
- return new OutputRequest(response, http, {method: 'GET', ...options});
13
+ return new OutputRequest(response, http, {method: 'GET', ...options});
14
14
  }
15
15
 
16
16
  send() {
17
17
  return new Promise((resolve, reject) => {
18
18
  try {
19
- this.#sendRequestOutputStream(
20
- this.#configureRequestOutputStream(this.#requestFunction, this.#response, this.#options, resolve, reject),
21
- this.#options);
22
-
23
- } catch (e) {
24
- throw new Error(e.message, {cause: 'INVALID_REQUEST'});
25
- }
26
- });
27
- }
28
-
29
- #configureRequestOutputStream(requestFunction, response, options, resolve, reject) {
30
- if (options.url != null) {
31
- return requestFunction(
32
- options.url,
33
- options,
34
- async (responseInputStream) => {
35
- await this.#flushResponseInputStream(responseInputStream, response, resolve, reject);
19
+ const requestOutputStream = this.#requestFunction(
20
+ this.#options.url,
21
+ this.#options,
22
+ async (responseInputStream) => {
23
+ try {
24
+ resolve(await this.#response
25
+ .copy(responseInputStream)
26
+ .flush());
27
+
28
+ } catch (e) {
29
+ reject(new Error(e.message, {cause: 'INVALID_REQUEST'}));
30
+ }
31
+ });
32
+
33
+ requestOutputStream.once('error', e => {
34
+ reject(new Error(e.message, {cause: 'INVALID_REQUEST'}));
36
35
  });
37
- }
38
36
 
39
- return requestFunction(
40
- options,
41
- async (responseInputStream) => {
42
- await this.#flushResponseInputStream(responseInputStream, response, resolve, reject);
43
- });
44
- }
37
+ if (this.#needToByWritten(this.#options)) {
38
+ requestOutputStream.write(this.#options.body);
39
+ }
45
40
 
46
- async #flushResponseInputStream(responseInputStream, response, resolve, reject) {
47
- try {
48
- resolve(await response
49
- .copy(responseInputStream)
50
- .flush());
41
+ requestOutputStream.end();
51
42
 
52
- } catch (e) {
53
- reject(e);
54
- }
55
- }
56
-
57
- #sendRequestOutputStream(requestOutputStream, options) {
58
- if (this.#needToByWritten(options)) {
59
- requestOutputStream.write(options.body);
60
- }
61
-
62
- requestOutputStream.end();
43
+ } catch (e) {
44
+ reject(new Error(e.message, {cause: 'INVALID_REQUEST'}));
45
+ }
46
+ });
63
47
  }
64
48
 
65
49
  #needToByWritten(options) {
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ OutputRequest: require('./OutputRequest')
3
+ };
@@ -11,27 +11,6 @@ module.exports = class InputResponse {
11
11
  return new InputResponse(inputStream, options);
12
12
  }
13
13
 
14
- flush() {
15
- return new Promise((resolve, reject) => {
16
- try {
17
- this.#inputStream.once('error', (e) => reject(new Error(e.message, {cause: 'INVALID_RESPONSE'})));
18
-
19
- let chunks = [];
20
- this.#inputStream.on('data', (chunk) => chunks.push(chunk));
21
- this.#inputStream.on('end', () => resolve(new InputResponse(this.#inputStream,
22
- {
23
- statusCode: this.#inputStream.statusCode,
24
- headers: new Headers(this.#inputStream.headers),
25
- body: Buffer.concat(chunks)
26
- }
27
- )));
28
-
29
- } catch (e) {
30
- throw new Error(e.message, {cause: 'INVALID_RESPONSE'});
31
- }
32
- });
33
- }
34
-
35
14
  statusCode() {
36
15
  return this.#options.statusCode;
37
16
  }
@@ -43,4 +22,27 @@ module.exports = class InputResponse {
43
22
  body() {
44
23
  return this.#options.body;
45
24
  }
25
+
26
+ async flush() {
27
+ return await new Promise((resolve, reject) => {
28
+ try {
29
+ this.#inputStream.once('error', (e) => reject(new Error(e.message, {cause: 'INVALID_RESPONSE'})));
30
+
31
+ let chunks = [];
32
+ this.#inputStream.on('data', (chunk) => chunks.push(chunk));
33
+ this.#inputStream.on('end', () => resolve(
34
+ new InputResponse(
35
+ this.#inputStream,
36
+ {
37
+ statusCode: this.#inputStream.statusCode,
38
+ headers: new Headers(this.#inputStream.headers),
39
+ body: Buffer.concat(chunks)
40
+ }
41
+ )
42
+ ));
43
+ } catch (e) {
44
+ throw new Error(e.message, {cause: 'INVALID_RESPONSE'});
45
+ }
46
+ });
47
+ }
46
48
  };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ InputResponse: require('./InputResponse')
3
+ };
package/src/js/index.js CHANGED
@@ -1,9 +1,5 @@
1
1
  module.exports = {
2
2
  server: require('./server'),
3
3
  client: require('./client'),
4
- bun: {
5
- server: {...require('./server'), ...require('./bun').server},
6
- client: {...require('./client'), ...require('./bun').client},
7
- bunttp: require('./bun').bunttp
8
- }
4
+ bun: require('./bun')
9
5
  }
@@ -7,10 +7,14 @@ module.exports = class LoggedServer {
7
7
  this.#logger = logger;
8
8
  }
9
9
 
10
+ options() {
11
+ return this.#origin.options();
12
+ }
13
+
10
14
  async start() {
11
15
  const server = await this.#origin.start();
12
16
 
13
- this.#logger.debug(`HttpServer is running at port: ${server.options().port}`);
17
+ this.#logger.debug(`HttpServer is running at port: ${this.#origin.options().port}`);
14
18
 
15
19
  return new LoggedServer(server, this.#logger);
16
20
  }
@@ -18,13 +22,8 @@ module.exports = class LoggedServer {
18
22
  async stop() {
19
23
  const server = await this.#origin.stop();
20
24
 
21
- this.#logger.debug(`HttpServer at port: ${server.options().port} is stopped`);
25
+ this.#logger.debug(`HttpServer at port: ${this.#origin.options().port} is stopped`);
22
26
 
23
27
  return new LoggedServer(server, this.#logger);
24
28
  }
25
-
26
-
27
- options() {
28
- return this.#origin.options();
29
- }
30
29
  }
@@ -15,31 +15,39 @@ module.exports = class Server {
15
15
  this.#server = server;
16
16
  }
17
17
 
18
+ options() {
19
+ return this.#options;
20
+ }
21
+
18
22
  start() {
19
23
  const server = this.#createServerFunction(async (requestStream, responseStream) => {
20
24
  try {
21
- return await (this.#response
22
- .copy(await this.#endpoints
23
- .handle(await (this.#request
24
- .copy(requestStream))
25
- .flush()), responseStream))
25
+ return await this.#response
26
+ .copy(responseStream,
27
+ await this.#endpoints
28
+ .handle(await this.#request
29
+ .copy(requestStream)
30
+ .flush()))
26
31
  .flush();
27
32
 
28
33
  } catch (e) {
29
34
  if (e.cause === 'INVALID_REQUEST') {
30
35
  return this.#response
31
- .copy({
32
- statusCode: 400,
33
- body: e.message
34
- }, responseStream)
36
+ .copy(responseStream,
37
+ {statusCode: 400, body: e.message})
38
+ .flush();
39
+ }
40
+
41
+ if (e.cause === 'HANDLER_NOT_FOUND') {
42
+ return this.#response
43
+ .copy(responseStream,
44
+ {statusCode: 501, body: e.message})
35
45
  .flush();
36
46
  }
37
47
 
38
48
  return this.#response
39
- .copy({
40
- statusCode: 500,
41
- body: 'Unexpected server error.'
42
- }, responseStream)
49
+ .copy(responseStream,
50
+ {statusCode: 500, body: 'Unexpected server error.'})
43
51
  .flush();
44
52
  }
45
53
  });
@@ -47,21 +55,21 @@ module.exports = class Server {
47
55
  return new Promise(resolve => {
48
56
  server.listen(
49
57
  this.#options,
50
- () => {
51
- resolve(new Server(
52
- this.#endpoints,
53
- this.#options,
54
- this.#request,
55
- this.#response,
56
- this.#createServerFunction,
57
- server));
58
- }
58
+ () => resolve(new Server(
59
+ this.#endpoints,
60
+ this.#options,
61
+ this.#request,
62
+ this.#response,
63
+ this.#createServerFunction,
64
+ server))
59
65
  );
60
66
  });
61
67
  }
62
68
 
63
69
  stop() {
64
70
  return new Promise(resolve => {
71
+ console.log('stop ', this.#server);
72
+
65
73
  this.#server.close(
66
74
  () => resolve(new Server(
67
75
  this.#endpoints,
@@ -72,8 +80,4 @@ module.exports = class Server {
72
80
  );
73
81
  });
74
82
  }
75
-
76
- options() {
77
- return this.#options;
78
- }
79
83
  };
@@ -1,24 +1,17 @@
1
1
  module.exports = class Endpoint {
2
- #method;
3
- #path;
2
+ #route;
4
3
 
5
- constructor(method, path) {
6
- this.#method = method;
7
- this.#path = path;
4
+ constructor(route) {
5
+ this.#route = route;
8
6
  }
9
7
 
10
- copy(method = this.#method, path = this.#path) {
11
- return new Endpoint(method, path);
8
+ route() {
9
+ return this.#route;
12
10
  }
13
11
 
14
- route() {
12
+ async handle() {
15
13
  return {
16
- method: this.#method.toString().toUpperCase(),
17
- path: this.#path.toString().toLowerCase()
14
+ statusCode: 200
18
15
  };
19
16
  }
20
-
21
- async handle(request) {
22
- return {};
23
- }
24
17
  }
@@ -1,26 +1,36 @@
1
1
  module.exports = class Endpoints {
2
- #collection;
2
+ #map;
3
3
 
4
- constructor(collection = []) {
5
- this.#collection = collection;
4
+ constructor(collection = [], map = new Map()) {
5
+ this.#map = map;
6
+ collection.forEach((endpoint) => {
7
+ if (!this.#map.has(endpoint.route().path.toString().toLowerCase())) {
8
+ this.#map.set(endpoint.route().path.toString().toLowerCase(), new Map());
9
+ }
10
+
11
+ this.#map
12
+ .get(endpoint.route().path.toString().toLowerCase())
13
+ .set(endpoint.route().method.toString().toUpperCase(),
14
+ endpoint);
15
+ });
6
16
  }
7
17
 
8
- copy(collection = this.#collection) {
9
- return new Endpoints(collection);
18
+ copy(collection, map = this.#map) {
19
+ return new Endpoints(collection, map);
10
20
  }
11
21
 
12
22
  async handle(request) {
13
- const endpoint = this.#collection
14
- .find(endpoint => endpoint.route().method === request.route().method
15
- && endpoint.route().path === request.route().path);
16
-
17
- if (endpoint == null) {
18
- return {
19
- statusCode: 501,
20
- body: 'There are no handler for request.'
21
- }
23
+ if (!this.#map.has(request.route().path.toString().toLowerCase())
24
+ || !this.#map
25
+ .get(request.route().path.toString().toLowerCase())
26
+ .has(request.route().method.toString().toUpperCase())
27
+ ) {
28
+ throw new Error('There are no handler for request.', {cause: 'HANDLER_NOT_FOUND'});
22
29
  }
23
30
 
24
- return await endpoint.handle(request);
31
+ return await this.#map
32
+ .get(request.route().path.toString().toLowerCase())
33
+ .get(request.route().method.toString().toUpperCase())
34
+ .handle(request);
25
35
  }
26
36
  }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ Endpoint: require('./Endpoint'),
3
+ Endpoints: require('./Endpoints'),
4
+ };
@@ -1,13 +1,7 @@
1
1
  module.exports = {
2
2
  Server: require('./Server'),
3
3
  LoggedServer: require('./LoggedServer'),
4
- Endpoint: require('./endpoint/Endpoint'),
5
- LoggedEndpoint: require('./endpoint/LoggedEndpoint'),
6
- Endpoints: require('./endpoint/Endpoints'),
7
- InputRequest: require('./request/InputRequest'),
8
- JsonInputRequest: require('./request/JsonInputRequest'),
9
- LoggedInputRequest: require('./request/LoggedInputRequest'),
10
- OutputResponse: require('./response/OutputResponse'),
11
- JsonOutputResponse: require('./response/JsonOutputResponse'),
12
- LoggedOutputResponse: require('./response/LoggedOutputResponse')
4
+ endpoint: require('./endpoint'),
5
+ request: require('./request'),
6
+ response: require('./response')
13
7
  }
@@ -11,6 +11,22 @@ module.exports = class InputRequest {
11
11
  return new InputRequest(inputStream, options);
12
12
  }
13
13
 
14
+ route() {
15
+ return this.#options.route;
16
+ }
17
+
18
+ query() {
19
+ return this.#options.query;
20
+ }
21
+
22
+ body() {
23
+ return this.#options.body;
24
+ }
25
+
26
+ headers() {
27
+ return this.#options.headers;
28
+ }
29
+
14
30
  flush() {
15
31
  return new Promise((resolve, reject) => {
16
32
  try {
@@ -23,36 +39,19 @@ module.exports = class InputRequest {
23
39
  this.#inputStream.on('end', () => resolve(new InputRequest(
24
40
  this.#inputStream,
25
41
  {
26
- method: this.#inputStream.method,
27
- path: new URL(this.#inputStream.url, 'http://dummy').pathname,
28
- query: new URL(this.#inputStream.url, 'http://dummy').searchParams,
42
+ route: {
43
+ method: this.#inputStream.method,
44
+ path: new URL(this.#inputStream.url, 'http://url').pathname
45
+ },
46
+ query: new URL(this.#inputStream.url, 'http://url').searchParams,
29
47
  headers: new Headers(this.#inputStream.headers),
30
- body: Buffer.concat(chunks)
48
+ body: Buffer.concat(chunks),
31
49
  }
32
50
  )));
33
51
 
34
52
  } catch (e) {
35
- throw new Error(e.message, {cause: 'INVALID_REQUEST'});
53
+ reject(new Error(e.message, {cause: 'INVALID_REQUEST'}));
36
54
  }
37
55
  });
38
56
  }
39
-
40
- route() {
41
- return {
42
- method: this.#options.method.toString().toUpperCase(),
43
- path: this.#options.path.toString().toLowerCase()
44
- };
45
- }
46
-
47
- query() {
48
- return this.#options.query;
49
- }
50
-
51
- body() {
52
- return this.#options.body;
53
- }
54
-
55
- headers() {
56
- return this.#options.headers;
57
- }
58
57
  };
@@ -13,19 +13,6 @@ module.exports = class LoggedInputRequest {
13
13
  return new LoggedInputRequest(origin, logger, inputStream);
14
14
  }
15
15
 
16
- async flush() {
17
- this.#logger.debug(`HttpRequest: [${this.#inputStream.method}] ${this.#inputStream.url} ${JSON.stringify(this.#inputStream.headers)}`);
18
-
19
- try {
20
- return new LoggedInputRequest(await this.#origin.flush(), this.#logger);
21
-
22
- } catch (e) {
23
- this.#logger.error(`HttpRequest: [${this.#inputStream.method}] ${this.#inputStream.url} error: ${e.message}`, e);
24
-
25
- throw e;
26
- }
27
- }
28
-
29
16
  route() {
30
17
  return this.#origin.route();
31
18
  }
@@ -41,4 +28,17 @@ module.exports = class LoggedInputRequest {
41
28
  headers() {
42
29
  return this.#origin.headers();
43
30
  }
31
+
32
+ async flush() {
33
+ this.#logger.debug(`HttpRequest: [${this.#inputStream.method}] ${this.#inputStream.url} ${JSON.stringify(this.#inputStream.headers)}`);
34
+
35
+ try {
36
+ return new LoggedInputRequest(await this.#origin.flush(), this.#logger);
37
+
38
+ } catch (e) {
39
+ this.#logger.error(`HttpRequest: [${this.#inputStream.method}] ${this.#inputStream.url} error: ${e.message}`, e);
40
+
41
+ throw e;
42
+ }
43
+ }
44
44
  }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ InputRequest: require('./InputRequest'),
3
+ LoggedInputRequest: require('./LoggedInputRequest')
4
+ };
@@ -11,10 +11,6 @@ module.exports = class LoggedOutputResponse {
11
11
  return new LoggedOutputResponse(origin, logger);
12
12
  }
13
13
 
14
- update(options) {
15
- return new LoggedOutputResponse(this.#origin.update(options), this.#logger);
16
- }
17
-
18
14
  flush() {
19
15
  const outputStream = this.#loggedFlush();
20
16
 
@@ -7,14 +7,10 @@ module.exports = class OutputResponse {
7
7
  this.#outputStream = outputStream;
8
8
  }
9
9
 
10
- copy(options = this.#options, outputStream = this.#outputStream) {
10
+ copy(outputStream = this.#outputStream, options = this.#options) {
11
11
  return new OutputResponse({...{statusCode: 200, headers: {}}, ...options}, outputStream);
12
12
  }
13
13
 
14
- update(options) {
15
- return new OutputResponse(this.#mergeOptions(this.#options, options), this.#outputStream);
16
- }
17
-
18
14
  flush() {
19
15
  try {
20
16
  this.#outputStream.writeHead(this.#options.statusCode, this.#options.headers)
@@ -29,24 +25,4 @@ module.exports = class OutputResponse {
29
25
  this.#outputStream.end();
30
26
  }
31
27
  }
32
-
33
- #mergeOptions(existedOptions, newOptions) {
34
- if (newOptions == null) {
35
- return existedOptions;
36
- }
37
-
38
- if (newOptions.statusCode != null) {
39
- existedOptions.statusCode = newOptions.statusCode;
40
- }
41
-
42
- if (newOptions.body != null) {
43
- existedOptions.body = newOptions.body;
44
- }
45
-
46
- if (newOptions.headers != null) {
47
- existedOptions.headers = {...existedOptions.headers, ...newOptions.headers};
48
- }
49
-
50
- return existedOptions;
51
- }
52
28
  }
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ OutputResponse: require('./OutputResponse'),
3
+ LoggedOutputResponse: require('./LoggedOutputResponse')
4
+ };
@@ -1,30 +0,0 @@
1
- module.exports = class LoggedEndpoint {
2
- #origin;
3
- #logger;
4
-
5
- constructor(origin, logger) {
6
- this.#origin = origin;
7
- this.#logger = logger;
8
- }
9
-
10
- copy(method, path, logger = this.#logger, origin = this.#origin.copy(method, path)) {
11
- return new LoggedEndpoint(origin, logger);
12
- }
13
-
14
- route() {
15
- return this.#origin.route();
16
- }
17
-
18
- async handle(request) {
19
- this.#logger.debug(`HttpEndpoint's handling [${request.route().method}] ${request.route().path}`);
20
-
21
- try {
22
- return await this.#origin.handle(request);
23
-
24
- } catch (e) {
25
- this.#logger.error(`HttpEndpoint's handling [${request.route().method}] ${request.route().path} error: ${e.message}`, e);
26
-
27
- throw e;
28
- }
29
- }
30
- }
@@ -1,51 +0,0 @@
1
- module.exports = class JsonInputRequest {
2
- #origin;
3
- #inputStream;
4
-
5
- constructor(origin, inputStream) {
6
- this.#origin = origin;
7
- this.#inputStream = inputStream;
8
- }
9
-
10
- copy(inputStream, options, origin = this.#origin.copy(inputStream, options)) {
11
- return new JsonInputRequest(origin, inputStream);
12
- }
13
-
14
- async flush() {
15
- if (this.#useChunkMethod(this.#inputStream.method) && !this.#validHeaders(new Headers(this.#inputStream.headers))) {
16
- throw new Error('Wrong content-type. Only application/json accepted.', {cause: 'INVALID_REQUEST'});
17
- }
18
-
19
- return new JsonInputRequest(await this.#origin.flush(), this.#inputStream);
20
- }
21
-
22
- route() {
23
- return this.#origin.route();
24
- }
25
-
26
- query() {
27
- return this.#origin.query();
28
- }
29
-
30
- body() {
31
- try {
32
- return JSON.parse(this.#origin.body().toString());
33
-
34
- } catch (e) {
35
- throw new Error('Wrong body format. Only JSON accepted.', {cause: 'INVALID_REQUEST'});
36
- }
37
- }
38
-
39
- headers() {
40
- return this.#origin.headers();
41
- }
42
-
43
- #useChunkMethod(requestMethod) {
44
- return ['POST', 'PUT'].some(method => method === requestMethod.toString().toUpperCase())
45
- }
46
-
47
- #validHeaders(requestHeaders) {
48
- return new Headers(requestHeaders).has('content-type')
49
- && new RegExp('^application\/json').test(new Headers(requestHeaders).get('content-type'));
50
- }
51
- }
@@ -1,45 +0,0 @@
1
- module.exports = class JsonOutputResponse {
2
- #origin;
3
- #options;
4
-
5
- constructor(origin, options) {
6
- this.#origin = origin;
7
- this.#options = options;
8
- }
9
-
10
- copy(options, outputStream, origin = this.#origin.copy(options, outputStream)) {
11
- return new JsonOutputResponse(origin, options);
12
- }
13
-
14
- update(options) {
15
- return new JsonOutputResponse(this.#origin.update(options));
16
- }
17
-
18
- flush() {
19
- const body = this.#options.body;
20
-
21
- if (body == null) {
22
- return this.#origin.flush();
23
- }
24
-
25
- if (typeof body === 'string') {
26
- try {
27
- JSON.parse(body);
28
-
29
- return this.#origin
30
- .update({headers: {'Content-Type': 'application/json; charset=utf-8'}})
31
- .flush();
32
-
33
- } catch (e) {
34
- return this.#origin.flush();
35
- }
36
- }
37
-
38
- return this.#origin
39
- .update({
40
- headers: {'Content-Type': 'application/json; charset=utf-8'},
41
- body: JSON.stringify(body)
42
- })
43
- .flush();
44
- }
45
- };