turbo-express-js 1.0.0 → 1.0.2

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.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # TurboServer - A Fast and Powerful Node.js Web Framework
2
2
 
3
- TurboServer is inspired by Express.js and offers a similar API to make it easy for developers familiar with Express to get started. In fact, TurboServer offers many of the same features and middleware that Express does, making it a great choice for developers who want a fast and efficient alternative to Express.
3
+ TurboServer is inspired by Express.js and offers a similar API to make it easy for developers familiar with Express to get started. In fact, TurboServer offers many of the same features and middleware that Express does, making it a great choice for developers who want a fast and efficient alternative to Express.
4
4
 
5
5
  #
6
6
 
7
- Additionally, TurboServer is built with an OOP architecture in mind, with Request and Response classes acting as interfaces. This makes it easy for developers to add new methods or override default functionality, leading to increased scalability and flexibility for your web applications.
7
+ Additionally, TurboServer is built with an OOP architecture in mind, with Request and Response classes acting as interfaces. This makes it easy for developers to add new methods or override default functionality, leading to increased scalability and flexibility for your web applications.
8
8
 
9
9
  #
10
10
 
@@ -51,7 +51,7 @@ Static
51
51
  The Static middleware serves static files from a specified folder:
52
52
 
53
53
  ``` javascript
54
- app.use(TurboServer.Static({ folder: '/public' }));
54
+ app.use("/*", TurboServer.Static({ folder: '/public' }));
55
55
  ```
56
56
 
57
57
 
@@ -69,7 +69,7 @@ The Upload middleware handles file uploads:
69
69
  The Validation middleware validates incoming requests against a specified schema (can validate by namespaces<params, query, body>):
70
70
 
71
71
  ``` javascript
72
- app.use(TurboServer.Validation({
72
+ app.use("/user/new", TurboServer.Validation({
73
73
  validations: [
74
74
  new TurboServer.ValidationSchema("username", [
75
75
  { name: TurboServer.ValidationMethodType.MINLENGTH, value: 3 },
@@ -87,7 +87,21 @@ The Authentication middleware handles user authentication:
87
87
  *work in progress still
88
88
 
89
89
  ``` javascript
90
- app.use(TurboServer.Authentication());
90
+ const mongoose = require("mongoose");
91
+
92
+ const conn = mongoose.createConnection("mongodb://localhost:27017/testtest");
93
+
94
+ const userModel = conn.model("User", new mongoose.Schema({
95
+ username: String,
96
+ password: String
97
+ }))
98
+
99
+ const authService = new TurboServer.JWTBcryptMongoDBAuthService({ UserModel: userModel, useDbUser: true });
100
+
101
+ app.post("/login", async (req, res) => await authService.simpleLogin(req, res));
102
+ app.post("/login-double", async (req, res) => await authService.doubleLoginWorkflow(req, res));
103
+
104
+ app.use("/api/v1/*", TurboServer.Authentication({ authentication_service: authService }));
91
105
  ```
92
106
 
93
107
  ## BuildForm
@@ -97,7 +111,7 @@ The BuildForm middleware parses some sort of model and can generate list of fiel
97
111
  *work in progress still
98
112
 
99
113
  ``` javascript
100
- app.use(TurboServer.BuildForm());
114
+ app.use("/api/v1/user/new", TurboServer.BuildForm());
101
115
  ```
102
116
 
103
117
  ## Cors
@@ -107,7 +121,7 @@ The Cors middleware adds CORS headers to responses:
107
121
  *work in progress still
108
122
 
109
123
  ``` javascript
110
- app.use(TurboServer.Cors());
124
+ app.use("/*", TurboServer.Cors());
111
125
  ```
112
126
 
113
127
 
@@ -125,7 +139,7 @@ Here's an example of a custom middleware function that logs the request method a
125
139
  next();
126
140
  }
127
141
 
128
- app.use(logger);
142
+ app.use("/*", logger);
129
143
  ```
130
144
 
131
145
  In the above example, we define a logger function that logs the request method and URL to the console, and then calls the next function to pass control to the next middleware function in the chain. We then use the app.use method to add the logger function as a middleware function for all routes in our application.
@@ -56,4 +56,41 @@ app.get("/hello1/:username",
56
56
  ] }),
57
57
 
58
58
 
59
- hello);
59
+ hello);
60
+
61
+
62
+
63
+
64
+
65
+ // ! $# BUILDING AUTHENTICATION SERVICE
66
+
67
+ class MyAuth extends TurboServer.AuthenticationService {
68
+
69
+ constructor() {
70
+ super();
71
+ this.devLogs = true;
72
+ this.nonBlocking = true;
73
+ this.useDbUser = true;
74
+ //console.log(this);
75
+ }
76
+
77
+ async find_user (login_value) {
78
+ if(login_value === "@kristina-trash") return { id: 1, username: "@kristina~trash", email: "kristina@perfect-evolution.eu" }
79
+ return null;
80
+ }
81
+ async compare_password (user, password) {
82
+ // console.log(user)
83
+ return true;
84
+ }
85
+
86
+
87
+
88
+
89
+ setMemory1 (key, value) {}
90
+ getMemory1 (key) {}
91
+
92
+
93
+
94
+ }
95
+
96
+ const authService = new MyAuth()
@@ -0,0 +1,49 @@
1
+ const TurboExpress = require("./lib/TurboServer");
2
+ const RequestInterface = require("./lib/types/RequestInterface");
3
+ const ResponseInterface = require("./lib/types/ResponseInterface");
4
+
5
+
6
+ const app = new TurboExpress(2);
7
+
8
+
9
+ TurboExpress.exeMaster(async () =>
10
+ {
11
+
12
+
13
+ console.log("Hello world");
14
+
15
+
16
+ });
17
+
18
+
19
+ class MyResponse extends ResponseInterface
20
+ {
21
+ mymethod () {
22
+ console.log("my method")
23
+ }
24
+ }
25
+
26
+ app.Response = MyResponse;
27
+
28
+ app.use("/*", TurboExpress.Cors({
29
+ // origins: ["http://localhost:3000"]
30
+ }));
31
+ /**
32
+ *
33
+ * @param {RequestInterface} req
34
+ * @param {ResponseInterface} res
35
+ */
36
+ function homepage (req, res) {
37
+ console.log("controller")
38
+ res.header("something", "wowowowo")
39
+ res.status(200).json({ user: { username: "kristina" } })
40
+ }
41
+ app.get("/something", homepage);
42
+ // app.options("/something", (req, res) => res.send(""));
43
+ // app.head("/something", (req, res) => res.send(""));
44
+ // app.get("/", homepage);
45
+
46
+ app.all("/something", homepage);
47
+
48
+
49
+ app.listen(3001, () => console.log("Server is running on port 3000"));
@@ -0,0 +1,50 @@
1
+ const TurboExpress = require("./lib/TurboServer");
2
+ const RequestInterface = require("./lib/types/RequestInterface");
3
+ const ResponseInterface = require("./lib/types/ResponseInterface");
4
+
5
+
6
+ const app = new TurboExpress(2);
7
+
8
+
9
+ TurboExpress.exeMaster(async () =>
10
+ {
11
+
12
+
13
+ console.log("Hello world");
14
+
15
+
16
+ });
17
+
18
+
19
+ class MyResponse extends ResponseInterface
20
+ {
21
+ mymethod () {
22
+ console.log("my method")
23
+ }
24
+ }
25
+
26
+ app.Response = MyResponse;
27
+
28
+ /**
29
+ *
30
+ * @param {RequestInterface} req
31
+ * @param {ResponseInterface} res
32
+ */
33
+ function homepage (req, res) {
34
+ const r = TurboExpress.SystemService.match_route(req.instance, req, res, [
35
+ { method: "get", path: "/:username/some" }
36
+ ], "", req.url().split("?")[0])
37
+
38
+ if(r) {
39
+ r.res.mymethod();
40
+ r.res.send("matched")
41
+ } else {
42
+ res.send("not")
43
+ }
44
+
45
+ }
46
+ app.get("/*", homepage);
47
+ app.get("/", homepage);
48
+
49
+
50
+ app.listen(3000, () => console.log("Server is running on port 3000"));
@@ -0,0 +1,44 @@
1
+ const TurboExpress = require("./lib/TurboServer");
2
+ const RequestInterface = require("./lib/types/RequestInterface");
3
+ const ResponseInterface = require("./lib/types/ResponseInterface");
4
+
5
+
6
+ const app = new TurboExpress(2);
7
+
8
+
9
+ TurboExpress.exeMaster(async () =>
10
+ {
11
+
12
+
13
+ console.log("Hello world");
14
+
15
+
16
+ });
17
+
18
+
19
+ class MyResponse extends ResponseInterface
20
+ {
21
+ mymethod () {
22
+ console.log("my method")
23
+ }
24
+ }
25
+
26
+ app.Response = MyResponse;
27
+
28
+ app.use("/*", (req, res, next) => {console.log("middleware"), next()})
29
+ app.useEndMiddleware("/*", (req, res, next) => console.log("end middleware"))
30
+ /**
31
+ *
32
+ * @param {RequestInterface} req
33
+ * @param {ResponseInterface} res
34
+ */
35
+ function homepage (req, res, next) {
36
+ console.log("controller")
37
+ res.status(200).json({ user: { username: "kristina" } })
38
+ next()
39
+ }
40
+ app.get("/something", homepage);
41
+ // app.get("/", homepage);
42
+
43
+
44
+ app.listen(3001, () => console.log("Server is running on port 3000"));
@@ -0,0 +1,107 @@
1
+ const TurboServer = require("./lib/TurboServer");
2
+
3
+ const RequestInterface = require("./lib/types/RequestInterface");
4
+ const ResponseInterface = require("./lib/types/ResponseInterface");
5
+ const Router = require("./lib/Router");
6
+
7
+
8
+ (async () => {
9
+
10
+ })();
11
+
12
+
13
+ const app = new TurboServer(1);
14
+
15
+ global.TURBO_EXPRESS = {
16
+ enviroment: "development"
17
+ }
18
+
19
+ const mongoose = require("mongoose");
20
+
21
+ const conn = mongoose.createConnection("mongodb://localhost:27017/testtest");
22
+
23
+ const userModel = conn.model("User", new mongoose.Schema({
24
+ username: String,
25
+ password: String
26
+ }))
27
+
28
+ ;(async () => {
29
+ console.log(await userModel.find());
30
+ })();
31
+
32
+
33
+ for (const key in object) {
34
+ if (Object.hasOwnProperty.call(object, key)) {
35
+ const element = object[key];
36
+
37
+ }
38
+ }
39
+
40
+
41
+ TurboServer.Log.dev("something");
42
+
43
+
44
+
45
+
46
+ app.get("/hi11", (req, res) => {});
47
+
48
+
49
+
50
+ app.post("/login", async (req, res) => await authService.simpleLogin(req, res));
51
+
52
+ app.post("/login-double", async (req, res) => await authService.doubleLoginWorkflow(req, res));
53
+
54
+ const authService = new TurboServer.JWTBcryptMongoDBAuthService({
55
+ UserModel: userModel, useDbUser: true
56
+ });
57
+
58
+ app.use("/asd*", TurboServer.Authentication({ authentication_service: authService }))
59
+
60
+ app.get("/something", (req, res) => {
61
+ let obj = {}
62
+ req.state.forEach((v, k) => obj[k] = v)
63
+ res.status(200).json(obj);
64
+ } )
65
+
66
+ app.get("/protected-route", async (req, res, next) => await authService.authenticated(req, res, next), (req, res) => {
67
+ let obj = {}
68
+ req.state.forEach((v, k) => obj[k] = v)
69
+ res.status(200).json(obj);
70
+ } )
71
+
72
+ /**
73
+ *
74
+ * @param {RequestInterface} req
75
+ * @param {ResponseInterface} res
76
+ */
77
+ function mydynamiccontroller (req, res) {
78
+
79
+ req.setState("something", 123123)
80
+
81
+ const result = TurboServer.SystemService.match_route(req, res, [
82
+ { method: "get", path: "/user/:username/read" },
83
+ { method: "post", path: "/user/new" }
84
+ ], "/api/v1/:projectname/", req.url().split("?")[0]);
85
+
86
+ if(!result) return res.status(404).json({ message: "not found || 404" })
87
+
88
+ console.log(result.res.status(200).json({params: result.req.paramsObj(), query: result.req.queriesObj(), url: result.req.url(), state: result.req.getStateObj()}));
89
+
90
+ //res.send("okk")
91
+ }
92
+
93
+ app.get("/api/v1/:projectname/*", mydynamiccontroller);
94
+
95
+
96
+ /**
97
+ *
98
+ * @param {RequestInterface} req
99
+ * @param {ResponseInterface} res
100
+ */
101
+ function controller (req, res) {
102
+ res.send(req.paramsObj().username)
103
+ }
104
+
105
+ app.get("/:username", controller);
106
+
107
+ app.listen(5000);
package/index.test.js CHANGED
@@ -1,116 +0,0 @@
1
- const TurboServer = require("./lib/TurboServer");
2
- const { MongoClient } = require('mongodb');
3
-
4
- const RequestInterface = require("./lib/types/RequestInterface");
5
- const ResponseInterface = require("./lib/types/ResponseInterface");
6
- const Router = require("./lib/Router");
7
-
8
-
9
-
10
- /**
11
- *
12
- * @param {RequestInterface} req
13
- * @param {ResponseInterface} res
14
- * @param {Function} next
15
- */
16
- async function mymiddleware (req, res, next)
17
- {
18
- req.setState("testone", "some test here");
19
-
20
- next();
21
- }
22
-
23
-
24
- const app = new TurboServer(2);
25
-
26
- app.get("/public/*", TurboServer.Static({ folder: "/public", cache: true }));
27
- app.post("/upload", TurboServer.Upload({ folder: "/storage", memory: true }));
28
-
29
-
30
- app.use("/*", TurboServer.Validation({ validations: [
31
- new TurboServer.ValidationSchema("username", [
32
- { name: TurboServer.ValidationMethodType.MINLENGTH, value: 3 },
33
- { name: TurboServer.ValidationMethodType.MAXLENGTH, value: 14 },
34
- { name: TurboServer.ValidationMethodType.ONEOF, value: ["XristinaMike"] }
35
- ], true, "hello", "body")
36
- ]}));
37
- app.use("/*", TurboServer.Authentication());
38
- app.use("/*", TurboServer.BuildForm());
39
- app.use("/*", TurboServer.Cors());
40
-
41
- // run method of request without running controller callback
42
- app.get("/hello/:username", TurboServer.RunMethod({ exe: [{ belog: "req", methodname: "fetchUsers", isAsync: true, inject: { somedata: "hello world some data injected to that method" } }] }));
43
-
44
- app.get("/", (req, res) => res.status(200).json({}))
45
-
46
- /**
47
- * @AUTHENTICATION MIDDLEWARE
48
- * @BUILD FORM MIDDLEWARE
49
- */
50
-
51
-
52
- /**
53
- *
54
- * @param {RequestInterface} req
55
- * @param {ResponseInterface} res
56
- * @param {Function} next
57
- */
58
- async function hello (req, res, next)
59
- {
60
- console.log(app.__link_routes = app.__link_routes.filter(f => f.path == "asdasd"))
61
- console.log(app.__link_routes)
62
-
63
- console.log("####", "hello")
64
- console.log(req.validData)
65
- next()
66
- res.status(201).json({result: 1, something: req.validateDataObj(), app: req.instance});
67
- }
68
-
69
-
70
- app.useEndMiddleware("/*", (req, res, next) => {console.log("middleware running after the controller method - #1"); next()}, (req, res, next) => {console.log("last middleware #2"); next()});
71
-
72
-
73
- app.use("/*", TurboServer.Cors({ }))
74
-
75
- app.get("/a/ok", (req, res) => {
76
- res.send("hello")
77
- })
78
-
79
- app.get("/hello/:username",
80
- TurboServer.RunMethod({ exe: [{ belog: "req", methodname: "something", isAsync: true, inject: { somedata: "hello world some data" } }] }),
81
- TurboServer.Validation({ validations: [
82
- new TurboServer.ValidationSchema("username", [
83
- { name: TurboServer.ValidationMethodType.MINLENGTH, value: 3 },
84
- { name: TurboServer.ValidationMethodType.MAXLENGTH, value: 14 },
85
- { name: TurboServer.ValidationMethodType.ONEOF, value: ["XristinaMike"] }
86
- ], true, "hello", "params")
87
- ] }), hello);
88
-
89
- app.get("/hello1/:username", hello);
90
-
91
- app.link("/hello1/:username",
92
- TurboServer.Validation({ validations: [
93
- new TurboServer.ValidationSchema("username", [
94
- { name: TurboServer.ValidationMethodType.MINLENGTH, value: 3 },
95
- { name: TurboServer.ValidationMethodType.MAXLENGTH, value: 14 },
96
- { name: TurboServer.ValidationMethodType.ONEOF, value: ["XristinaMike"] }
97
- ], true, "hello", "params")
98
- ]}),
99
-
100
- hello);
101
-
102
- const admin_router = new TurboServer.Router();
103
-
104
- admin_router.get("/admin/:username", (req, res) => { res.send(req.params().get("username")) });
105
-
106
- app.use("/api/v1/", admin_router)
107
-
108
-
109
- app.listen(5000);
110
-
111
- app.logRoutes();
112
-
113
- //console.log(app);
114
-
115
-
116
-
@@ -23,7 +23,7 @@ const Router = require("./Router");
23
23
  const cluster = require("cluster");
24
24
  const RequestInterface = require("./types/RequestInterface");
25
25
  const ResponseInterface = require("./types/ResponseInterface");
26
- const { matching_route, matching_nonexact_route } = require("./utils");
26
+ const { matching_route, matching_nonexact_route, Log } = require("./utils");
27
27
  const Route = require("./types/Route");
28
28
  const Middleware= require("./types/Middleware");
29
29
  const RequestMethods = require("./statictypes/RequestMethods");
@@ -37,13 +37,25 @@ const runmethod_middleware = require("./middlewares/runmethod_middleware");
37
37
  const buildform_middleware = require("./middlewares/buildform_middleware");
38
38
  const authentication_middleware = require("./middlewares/authentication_middleware");
39
39
  const cors_middleware = require("./middlewares/cors_middleware");
40
+ const AuthenticationService = require("./services/AuthenticationService");
41
+ const SystemService = require("./services/SystemService");
42
+ const JWTBcryptMongoDBAuthService = require("./types/default/JWTBcryptMongoDBAuthService");
40
43
 
41
44
 
42
45
  module.exports = class TurboServer
43
46
  {
44
47
  static Router = Router;
48
+ static AuthenticationService = AuthenticationService;
49
+
45
50
  static ValidationSchema = ValidationSchema;
46
51
  static ValidationMethodType = ValidationMethodType;
52
+
53
+ static SystemService = SystemService;
54
+ static JWTBcryptMongoDBAuthService = JWTBcryptMongoDBAuthService;
55
+
56
+
57
+ static Log = Log;
58
+
47
59
 
48
60
  /**
49
61
  * @typedef {Object} StaticOptions
@@ -60,8 +72,10 @@ module.exports = class TurboServer
60
72
 
61
73
  /**
62
74
  * @typedef {Object} CorsOptions
63
- * @property {String} folder - default /public
64
- * @property {Boolean} cache - default false
75
+ * @property {String[]} origins - default ["*"]
76
+ * @property {Boolean} credentials - default true
77
+ * @property {String[]} methods - default [GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS]
78
+ * @property {String[]} headers - default *
65
79
  *
66
80
  * @param {CorsOptions} CorsOptions
67
81
  * @returns
@@ -69,7 +83,10 @@ module.exports = class TurboServer
69
83
  static Cors (CorsOptions)
70
84
  {
71
85
  return cors_middleware.bind({
72
-
86
+ origins: CorsOptions.origins ? CorsOptions.origins : ["*"],
87
+ methods: CorsOptions.methods ? CorsOptions.methods : ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE", "OPTIONS"],
88
+ credentials: CorsOptions.credentials === false ? false : true,
89
+ headers: CorsOptions.headers || []
73
90
  })
74
91
  }
75
92
 
@@ -129,6 +146,7 @@ module.exports = class TurboServer
129
146
  /**
130
147
  *
131
148
  * @typedef {Object} AuthenticationOptions
149
+ * @property {AuthenticationService} authentication_service
132
150
  *
133
151
  * @param {AuthenticationOptions} AuthenticationOptions
134
152
  * @returns
@@ -136,7 +154,7 @@ module.exports = class TurboServer
136
154
  static Authentication (AuthenticationOptions={})
137
155
  {
138
156
  return authentication_middleware.bind({
139
-
157
+ authentication_service: AuthenticationOptions.authentication_service
140
158
  })
141
159
  }
142
160
 
@@ -153,6 +171,19 @@ module.exports = class TurboServer
153
171
  })
154
172
  }
155
173
 
174
+ /**
175
+ * Execute code only in master instance
176
+ *
177
+ * @param {Function} cb
178
+ */
179
+ static async exeMaster (cb)
180
+ {
181
+ if(cluster.isMaster)
182
+ {
183
+ await cb();
184
+ }
185
+ }
186
+
156
187
 
157
188
 
158
189
  /** @type{http.Server} */ #server;
@@ -181,6 +212,9 @@ module.exports = class TurboServer
181
212
  /** @type{RequestInterface} */ Request;
182
213
  /** @type{ResponseInterface} */ Response;
183
214
 
215
+
216
+ /** // todo this in server memory is still in development, need somehow share them between all processes that running on multi cluster server */
217
+
184
218
  /** @type {Map<String, Object>} */ appState = new Map();
185
219
  /** @type {Map<String, import("mongoose").Model} */ models = new Map();
186
220
  /** @type {Map<String, import("mongoose").Model} */ sqlModels = new Map(); // TODO later
@@ -220,6 +254,13 @@ module.exports = class TurboServer
220
254
  purge(path, ...callbacks){if(!cluster.isMaster) {this.__purge_routes.push(new Route(path, RequestMethods.PURGE, callbacks, this.__middlewares_begin, this.__middlewares_end));}}
221
255
  propfind(path, ...callbacks){if(!cluster.isMaster) {this.__propfind_routes.push(new Route(path, RequestMethods.PROPFIND, callbacks, this.__middlewares_begin, this.__middlewares_end));}}
222
256
 
257
+ all(path, ...callbacks){
258
+ if(!cluster.isMaster) {
259
+ const rMethods = new RequestMethods();
260
+ rMethods.forEach((m) => this[`__${m}_routes`].push(new Route(path, m, callbacks, this.__middlewares_begin, this.__middlewares_end)));
261
+ }
262
+ }
263
+
223
264
  use(path, ...callbackOrRouter)
224
265
  {
225
266
  if(callbackOrRouter[0] instanceof Router === true) {
@@ -259,6 +300,10 @@ module.exports = class TurboServer
259
300
  }
260
301
 
261
302
 
303
+ setAuthentication (authService)
304
+ {
305
+
306
+ }
262
307
 
263
308
 
264
309
  logRoutes ()
@@ -23,11 +23,11 @@ const ResponseInterface = require("../types/ResponseInterface");
23
23
  * @param {ResponseInterface} res
24
24
  * @param {*} next
25
25
  */
26
- module.exports = function authentication_middleware (req, res, next)
26
+ module.exports = async function authentication_middleware (req, res, next)
27
27
  {
28
28
 
29
- // comming soon;
29
+ const { authentication_service } = this;
30
30
 
31
- res.send("comming soon - authentication middleware");
31
+ return await authentication_service.authenticated(req, res, next);
32
32
 
33
33
  }
@@ -25,9 +25,26 @@ const ResponseInterface = require("../types/ResponseInterface");
25
25
  */
26
26
  module.exports = function cors_middleware (req, res, next)
27
27
  {
28
+ const { origins, methods, credentials, headers } = this;
28
29
 
29
- // comming soon;
30
+ res.header("Access-Control-Allow-Origin", origins.join(","));
31
+ res.header("Access-Control-Allow-Credentials", credentials);
32
+ res.header("Access-Control-Allow-Methods", methods.join(","));
33
+ res.header("Access-Control-Max-Age", 3600);
30
34
 
31
- res.send("comming soon - cors middleware");
35
+ let allowedHeaders = "";
36
+ const headers_req = req.headers();
37
+ for (const key in headers_req) {
38
+ if (Object.hasOwnProperty.call(headers_req, key)) {
39
+ if(key.toLowerCase() === "access-control-request-headers") { allowedHeaders = allowedHeaders + headers_req[key] + "," } else {
40
+ allowedHeaders = allowedHeaders + key + ","
41
+ }
42
+ }
43
+ }
44
+ res.header("Access-Control-Allow-Headers", (allowedHeaders + headers.join(",")).substring(
45
+ 0, (allowedHeaders + headers.join(",")).length - 1
46
+ ));
47
+
48
+ next();
32
49
 
33
50
  }