Forráskód Böngészése

Some refactoring, some clarification, etc.

Craig Fletcher 4 éve
szülő
commit
93c4277c65
7 módosított fájl, 68 hozzáadás és 62 törlés
  1. 12 9
      README.md
  2. 30 33
      src/easy-api.js
  3. 8 2
      src/index.js
  4. 6 6
      src/modules/check-schema.js
  5. 5 5
      src/routes/goodbye.js
  6. 5 5
      src/routes/hello.js
  7. 2 2
      src/routes/index.js

+ 12 - 9
README.md

@@ -18,13 +18,13 @@ simply factories with instances passed in.
 
 Import start from easy-api.js, call like so:
 ```
-start(
+start({
   routes[], 
-  host = '127.0.0.1', 
-  port = 8080, 
-  dbOpts{}, 
-  serverOpts{}
-)
+  host, 
+  port, 
+  redisOpts{}, 
+  restifyOpts{}
+})
 ```
 
 The included example uses docker and docker-compose, so the db host is set to
@@ -46,8 +46,8 @@ hash to use as an ID.
 
 Routes are defined as simple factories, passed a db wrapper, yup and log instance as
 an object ({db, yup, log}) and expected to return:
-  * type: HTTP verb, e.g. `get`
-  * route: restify path string, e.g. `/api/hello/:name`
+  * verb: HTTP verb, e.g. `get`
+  * path: restify path string, e.g. `/api/hello/:name`
   * handler: restify handler function for route
   * schema (optional): yup schema to validate against
 
@@ -56,4 +56,7 @@ an object ({db, yup, log}) and expected to return:
 
 If a route passes a schema, the request will be validated against it:
   * get requests validate against `req.params`
-  * post requests validate against `req.data`
+  * post requests validate against `req.body`
+
+When validation fails, a HTTP 400 is returned and the handler is not
+processed.

+ 30 - 33
src/easy-api.js

@@ -6,48 +6,45 @@ import { checkReqBody, checkParams } from './modules/check-schema.js';
 import dbWrapper from './modules/db.js';
 import logger from './modules/logging.js';
 
-function registerRoute(db, server, log) {
-  return function setupRoute(routeSetup) {
-    const route = routeSetup({ db, yup, log });
-
-    if (route.schema) {
-      switch (route.type) {
-        case 'get':
-          server.get(route.route, checkParams(route.schema, log, route.route), route.handler);
-          break;
-        case 'post':
-          server.post(route.route, checkReqBody(route.schema, log, route.route), route.handler);
-          break;
-        default:
-          throw new Error();
-      }
-    } else {
-      switch (route.type) {
-        case 'get':
-          server.get(route.route, route.handler);
-          break;
-        case 'post':
-          server.post(route.route, route.handler);
-          break;
-        default:
-          throw new Error();
-      }
+function setupRoute(routeFactory, db, server, log) {
+  const route = routeFactory({ db, yup, log });
+
+  if (route.schema) {
+    switch (route.verb) {
+      case 'get':
+        server.get(route.path, checkParams(route.schema, log, route.path), route.handler);
+        break;
+      case 'post':
+        server.post(route.path, checkReqBody(route.schema, log, route.path), route.handler);
+        break;
+      default:
+        throw new Error();
     }
-  };
+  } else {
+    switch (route.verb) {
+      case 'get':
+        server.get(route.path, route.handler);
+        break;
+      case 'post':
+        server.post(route.path, route.handler);
+        break;
+      default:
+        throw new Error();
+    }
+  }
 }
 
-function start(routes, host = '127.0.0.1', port = 8080, dbOpts, serverOpts) {
-  const client = redis.createClient(dbOpts);
+function start({ routes, host, port, redisOpts, restifyOpts }) {
+  const client = redis.createClient(redisOpts);
 
   client.on('connect', () => {
     logger.info('connected to db, starting server...');
-    const server = restify.createServer(serverOpts);
+    const server = restify.createServer(restifyOpts);
     const db = dbWrapper(client);
-    const setupRoute = registerRoute(db, server, logger);
     server.use(restify.plugins.bodyParser());
 
-    routes.forEach(route => {
-      setupRoute(route);
+    routes.forEach(routeFactory => {
+      setupRoute(routeFactory, db, server, logger);
     });
 
     server.listen(port, host, () => {

+ 8 - 2
src/index.js

@@ -1,5 +1,11 @@
 import { env } from 'process';
 import start from './easy-api.js';
-import routes from './routes/index.js';
+import routeFactories from './routes/index.js';
 
-start(routes, '0.0.0.0', 8080, { host: 'redis', password: env.REDIS_PASS }, { name: 'example-easy-api' });
+start({
+  routes: routeFactories,
+  host: '0.0.0.0',
+  port: 8080,
+  redisOpts: { host: 'redis', password: env.REDIS_PASS },
+  restifyOpts: { name: 'example-easy-api' },
+});

+ 6 - 6
src/modules/check-schema.js

@@ -1,24 +1,24 @@
-export function checkReqBody(schema, log, route) {
+export function checkReqBody(schema, log, path) {
   return function checkValid(req, res, next) {
     schema.isValid(req.body).then(valid => {
       if (valid) {
         next();
       } else {
-        res.send('Incorrect request');
-        log.debug(`Invalid request for route: ${route}, ${JSON.stringify(req.params)}`);
+        res.send(400, { error: 'Bad request' });
+        log.debug(`Invalid request for route: ${path}, ${JSON.stringify(req.params)}`);
       }
     });
   };
 }
 
-export function checkParams(schema, log, route) {
+export function checkParams(schema, log, path) {
   return function checkValid(req, res, next) {
     schema.isValid(req.params).then(valid => {
       if (valid) {
         next();
       } else {
-        res.send('Incorrect request');
-        log.debug(`Invalid request for route: ${route}, ${JSON.stringify(req.params)}`);
+        res.send(400, { error: 'Bad request' });
+        log.debug(`Invalid request for route: ${path}, ${JSON.stringify(req.params)}`);
       }
     });
   };

+ 5 - 5
src/routes/goodbye.js

@@ -1,15 +1,15 @@
-function setup({ db, yup, log }) {
+function routeFactory({ db, yup, log }) {
   return {
-    type: 'post',
-    route: '/goodbye',
+    verb: 'post',
+    path: '/goodbye',
     handler(req, res, next) {
       const contentPath = ['visits', req.body.name];
       db.get(contentPath, reply => {
         const visits = reply >= 0 ? Number(reply) + 1 : 1;
         log.info(`Visited by ${req.body.name}.`);
         res.send(`hello ${req.body.name}. You have visited ${visits} times.`);
-        db.set(contentPath, visits);
         next();
+        db.set(contentPath, visits);
       });
     },
     schema: yup.object().shape({
@@ -18,4 +18,4 @@ function setup({ db, yup, log }) {
   };
 }
 
-export default setup;
+export default routeFactory;

+ 5 - 5
src/routes/hello.js

@@ -1,15 +1,15 @@
-function setup({ db, yup, log }) {
+function routeFactory({ db, yup, log }) {
   return {
-    type: 'get',
-    route: '/hello/:name',
+    verb: 'get',
+    path: '/hello/:name',
     handler(req, res, next) {
       const contentPath = ['visits', req.params.name];
       db.get(contentPath, reply => {
         const visits = reply >= 0 ? Number(reply) + 1 : 1;
         log.info(`Visited by ${req.params.name}.`);
         res.send(`hello ${req.params.name}. You have visited ${visits} times.`);
-        db.set(contentPath, visits);
         next();
+        db.set(contentPath, visits);
       });
     },
     schema: yup.object().shape({
@@ -18,4 +18,4 @@ function setup({ db, yup, log }) {
   };
 }
 
-export default setup;
+export default routeFactory;

+ 2 - 2
src/routes/index.js

@@ -2,6 +2,6 @@ import hello from './hello.js';
 import goodbye from './goodbye.js';
 
 // re-exporting here for tidiness
-const routes = [hello, goodbye];
+const routeFactories = [hello, goodbye];
 
-export default routes;
+export default routeFactories;