From 318fa626fe0772f19178a063b9a2258b972836fb Mon Sep 17 00:00:00 2001
From: bill bittner <bittner.w@gmail.com>
Date: Wed, 28 Mar 2018 17:35:41 -0700
Subject: [PATCH] updated api and asset route folders

---
 server/routes/api/channelAvailability.js      |  25 ++
 server/routes/api/channelClaims.js            |  31 +++
 server/routes/api/channelData.js              |  30 +++
 .../{apiRoutes => api}/channelShortId.js      |   7 +-
 server/routes/api/claimAvailability.js        |  25 ++
 server/routes/api/claimData.js                |  27 ++
 server/routes/api/claimGet.js                 |  39 +++
 server/routes/api/claimLongId.js              |  35 +++
 server/routes/api/claimPublish.js             |  69 ++++++
 server/routes/api/claimResolve.js             |  22 ++
 server/routes/api/claimShortId.js             |  21 ++
 server/routes/api/claimsList.js               |  22 ++
 server/routes/api/fileAvailability.js         |  33 +++
 server/routes/api/index.js                    |  29 +++
 server/routes/apiRoutes/index.js              |   5 -
 server/routes/apiRoutes/otherRoutes.js        | 232 ------------------
 server/routes/asset/index.js                  |   8 +
 server/routes/asset/serveAssetByClaim.js      |  44 ++++
 .../serveAssetByIdentifierAndClaim.js}        |  53 ++--
 server/routes/{ => auth}/auth-routes.js       |   0
 .../routes/{ => fallback}/fallback-routes.js  |   2 +-
 server/routes/{ => page}/page-routes.js       |   4 +-
 speech.js                                     |  12 +-
 23 files changed, 488 insertions(+), 287 deletions(-)
 create mode 100644 server/routes/api/channelAvailability.js
 create mode 100644 server/routes/api/channelClaims.js
 create mode 100644 server/routes/api/channelData.js
 rename server/routes/{apiRoutes => api}/channelShortId.js (64%)
 create mode 100644 server/routes/api/claimAvailability.js
 create mode 100644 server/routes/api/claimData.js
 create mode 100644 server/routes/api/claimGet.js
 create mode 100644 server/routes/api/claimLongId.js
 create mode 100644 server/routes/api/claimPublish.js
 create mode 100644 server/routes/api/claimResolve.js
 create mode 100644 server/routes/api/claimShortId.js
 create mode 100644 server/routes/api/claimsList.js
 create mode 100644 server/routes/api/fileAvailability.js
 create mode 100644 server/routes/api/index.js
 delete mode 100644 server/routes/apiRoutes/index.js
 delete mode 100644 server/routes/apiRoutes/otherRoutes.js
 create mode 100644 server/routes/asset/index.js
 create mode 100644 server/routes/asset/serveAssetByClaim.js
 rename server/routes/{asset-routes.js => asset/serveAssetByIdentifierAndClaim.js} (52%)
 rename server/routes/{ => auth}/auth-routes.js (100%)
 rename server/routes/{ => fallback}/fallback-routes.js (72%)
 rename server/routes/{ => page}/page-routes.js (87%)

diff --git a/server/routes/api/channelAvailability.js b/server/routes/api/channelAvailability.js
new file mode 100644
index 00000000..3ac716b9
--- /dev/null
+++ b/server/routes/api/channelAvailability.js
@@ -0,0 +1,25 @@
+const { checkChannelAvailability } = require('../../controllers/publishController.js');
+const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to check whether site has published to a channel
+
+*/
+
+const channelAvailability = () => {
+  return ({ ip, originalUrl, params: { name } }, res) => {
+    const gaStartTime = Date.now();
+    checkChannelAvailability(name)
+      .then(availableName => {
+        res.status(200).json(availableName);
+        sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = channelAvailability;
diff --git a/server/routes/api/channelClaims.js b/server/routes/api/channelClaims.js
new file mode 100644
index 00000000..cc354f8d
--- /dev/null
+++ b/server/routes/api/channelClaims.js
@@ -0,0 +1,31 @@
+const { getChannelClaims } = require('../../controllers/serveController.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+const NO_CHANNEL = 'NO_CHANNEL';
+
+/*
+
+  route to get all claims for channel
+
+*/
+
+const channelClaims = () => {
+  return ({ ip, originalUrl, body, params }, res) => {
+    const channelName = params.channelName;
+    let channelClaimId = params.channelClaimId;
+    if (channelClaimId === 'none') channelClaimId = null;
+    const page = params.page;
+    getChannelClaims(channelName, channelClaimId, page)
+      .then(data => {
+        if (data === NO_CHANNEL) {
+          return res.status(404).json({success: false, message: 'No matching channel was found'});
+        }
+        res.status(200).json({success: true, data});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = channelClaims;
diff --git a/server/routes/api/channelData.js b/server/routes/api/channelData.js
new file mode 100644
index 00000000..04a823c6
--- /dev/null
+++ b/server/routes/api/channelData.js
@@ -0,0 +1,30 @@
+const { getChannelData } = require('../../controllers/serveController.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+const NO_CHANNEL = 'NO_CHANNEL';
+
+/*
+
+  route to get data for a channel
+
+*/
+
+const channelData = () => {
+  return ({ ip, originalUrl, body, params }, res) => {
+    const channelName = params.channelName;
+    let channelClaimId = params.channelClaimId;
+    if (channelClaimId === 'none') channelClaimId = null;
+    getChannelData(channelName, channelClaimId, 0)
+      .then(data => {
+        if (data === NO_CHANNEL) {
+          return res.status(404).json({success: false, message: 'No matching channel was found'});
+        }
+        res.status(200).json({success: true, data});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = channelData;
diff --git a/server/routes/apiRoutes/channelShortId.js b/server/routes/api/channelShortId.js
similarity index 64%
rename from server/routes/apiRoutes/channelShortId.js
rename to server/routes/api/channelShortId.js
index 46ec4486..15b4e655 100644
--- a/server/routes/apiRoutes/channelShortId.js
+++ b/server/routes/api/channelShortId.js
@@ -1,6 +1,3 @@
-const logger = require('winston');
-// const { details: { host } } = require('siteConfig.js');
-// const { db } = require('mysqlConfig.js');
 const { handleErrorResponse } = require('helpers/errorHandlers.js');
 
 /*
@@ -9,10 +6,8 @@ route to get a short channel id from long channel Id
 
 */
 
-const channelShortIdRoute = (db, host) => {
+const channelShortIdRoute = (db) => {
   return ({ ip, originalUrl, params }, res) => {
-    console.log('hello from channelShortIdRoute');
-    logger.debug('host:', host);
     db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)
       .then(shortId => {
         res.status(200).json(shortId);
diff --git a/server/routes/api/claimAvailability.js b/server/routes/api/claimAvailability.js
new file mode 100644
index 00000000..2d1b44a1
--- /dev/null
+++ b/server/routes/api/claimAvailability.js
@@ -0,0 +1,25 @@
+const { claimNameIsAvailable } = require('../../controllers/publishController.js');
+const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to check whether this site published to a claim
+
+*/
+
+const claimAvailability = () => {
+  return ({ ip, originalUrl, params: { name } }, res) => {
+    const gaStartTime = Date.now();
+    claimNameIsAvailable(name)
+      .then(result => {
+        res.status(200).json(result);
+        sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimAvailability;
diff --git a/server/routes/api/claimData.js b/server/routes/api/claimData.js
new file mode 100644
index 00000000..0d307faa
--- /dev/null
+++ b/server/routes/api/claimData.js
@@ -0,0 +1,27 @@
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to return data for a claim
+
+*/
+
+const claimData = (db) => {
+  return ({ ip, originalUrl, body, params }, res) => {
+    const claimName = params.claimName;
+    let claimId = params.claimId;
+    if (claimId === 'none') claimId = null;
+    db.Claim.resolveClaim(claimName, claimId)
+      .then(claimInfo => {
+        if (!claimInfo) {
+          return res.status(404).json({success: false, message: 'No claim could be found'});
+        }
+        res.status(200).json({success: true, data: claimInfo});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimData;
diff --git a/server/routes/api/claimGet.js b/server/routes/api/claimGet.js
new file mode 100644
index 00000000..d1637aad
--- /dev/null
+++ b/server/routes/api/claimGet.js
@@ -0,0 +1,39 @@
+const { getClaim } = require('../../helpers/lbryApi.js');
+const { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to get a claim
+
+*/
+
+const claimGet = (db) => {
+  return ({ ip, originalUrl, params }, res) => {
+    const name = params.name;
+    const claimId = params.claimId;
+    // resolve the claim
+    db.Claim.resolveClaim(name, claimId)
+      .then(resolveResult => {
+        // make sure a claim actually exists at that uri
+        if (!resolveResult) {
+          throw new Error('No matching uri found in Claim table');
+        }
+        let fileData = createFileData(resolveResult);
+        // get the claim
+        return Promise.all([fileData, getClaim(`${name}#${claimId}`)]);
+      })
+      .then(([ fileData, getResult ]) => {
+        fileData = addGetResultsToFileData(fileData, getResult);
+        return Promise.all([db.upsert(db.File, fileData, {name, claimId}, 'File'), getResult]);
+      })
+      .then(([ fileRecord, {message, completed} ]) => {
+        res.status(200).json({ success: true, message, completed });
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimGet;
diff --git a/server/routes/api/claimLongId.js b/server/routes/api/claimLongId.js
new file mode 100644
index 00000000..f137e0a4
--- /dev/null
+++ b/server/routes/api/claimLongId.js
@@ -0,0 +1,35 @@
+const { getClaimId } = require('../../controllers/serveController.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+const NO_CHANNEL = 'NO_CHANNEL';
+const NO_CLAIM = 'NO_CLAIM';
+
+/*
+
+  route to get a long claim id
+
+*/
+
+const claimLongId = () => {
+  return ({ ip, originalUrl, body, params }, res) => {
+    const channelName = body.channelName;
+    const channelClaimId = body.channelClaimId;
+    const claimName = body.claimName;
+    const claimId = body.claimId;
+    getClaimId(channelName, channelClaimId, claimName, claimId)
+      .then(result => {
+        if (result === NO_CHANNEL) {
+          return res.status(404).json({success: false, message: 'No matching channel could be found'});
+        }
+        if (result === NO_CLAIM) {
+          return res.status(404).json({success: false, message: 'No matching claim id could be found'});
+        }
+        res.status(200).json({success: true, data: result});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimLongId;
diff --git a/server/routes/api/claimPublish.js b/server/routes/api/claimPublish.js
new file mode 100644
index 00000000..9852714e
--- /dev/null
+++ b/server/routes/api/claimPublish.js
@@ -0,0 +1,69 @@
+const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles } = require('../../helpers/publishHelpers.js');
+const { claimNameIsAvailable, publish } = require('../../controllers/publishController.js');
+const { authenticateUser } = require('../../auth/authentication.js');
+const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to publish a claim through the daemon
+
+*/
+
+const claimPublish = (db, host) => {
+  return ({ body, files, headers, ip, originalUrl, user }, res) => {
+    // define variables
+    let  channelName, channelId, channelPassword, description, fileName, filePath, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title;
+    // record the start time of the request
+    gaStartTime = Date.now();
+    // validate the body and files of the request
+    try {
+      // validateApiPublishRequest(body, files);
+      ({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body));
+      ({fileName, filePath, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files));
+      ({channelName, channelId, channelPassword} = body);
+    } catch (error) {
+      return res.status(400).json({success: false, message: error.message});
+    }
+    // check channel authorization
+    Promise
+      .all([
+        authenticateUser(channelName, channelId, channelPassword, user),
+        claimNameIsAvailable(name),
+        createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail),
+        createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw),
+      ])
+      .then(([{channelName, channelClaimId}, validatedClaimName, publishParams, thumbnailPublishParams]) => {
+        // add channel details to the publish params
+        if (channelName && channelClaimId) {
+          publishParams['channel_name'] = channelName;
+          publishParams['channel_id'] = channelClaimId;
+        }
+        // publish the thumbnail
+        if (thumbnailPublishParams) {
+          publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);
+        }
+        // publish the asset
+        return publish(publishParams, fileName, fileType);
+      })
+      .then(result => {
+        res.status(200).json({
+          success: true,
+          message: 'publish completed successfully',
+          data   : {
+            name,
+            claimId: result.claim_id,
+            url    : `${host}/${result.claim_id}/${name}`,
+            lbryTx : result,
+          },
+        });
+        // record the publish end time and send to google analytics
+        sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimPublish;
diff --git a/server/routes/api/claimResolve.js b/server/routes/api/claimResolve.js
new file mode 100644
index 00000000..3b9cfd32
--- /dev/null
+++ b/server/routes/api/claimResolve.js
@@ -0,0 +1,22 @@
+const { resolveUri } = require('../../helpers/lbryApi.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to run a resolve request on the daemon
+
+*/
+
+const claimResolve = () => {
+  return ({ headers, ip, originalUrl, params }, res) => {
+    resolveUri(`${params.name}#${params.claimId}`)
+      .then(resolvedUri => {
+        res.status(200).json(resolvedUri);
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimResolve;
diff --git a/server/routes/api/claimShortId.js b/server/routes/api/claimShortId.js
new file mode 100644
index 00000000..e6983a78
--- /dev/null
+++ b/server/routes/api/claimShortId.js
@@ -0,0 +1,21 @@
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to get a short claim id from long claim Id
+
+*/
+
+const claimShortId = (db) => {
+  return ({ ip, originalUrl, body, params }, res) => {
+    db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)
+      .then(shortId => {
+        res.status(200).json({success: true, data: shortId});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimShortId;
diff --git a/server/routes/api/claimsList.js b/server/routes/api/claimsList.js
new file mode 100644
index 00000000..50e4a5e7
--- /dev/null
+++ b/server/routes/api/claimsList.js
@@ -0,0 +1,22 @@
+const { getClaimList } = require('../../helpers/lbryApi.js');
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to get list of claims
+
+*/
+
+const claimList = (db) => {
+  return ({ ip, originalUrl, params }, res) => {
+    getClaimList(params.name)
+      .then(claimsList => {
+        res.status(200).json(claimsList);
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = claimList;
diff --git a/server/routes/api/fileAvailability.js b/server/routes/api/fileAvailability.js
new file mode 100644
index 00000000..11357f1a
--- /dev/null
+++ b/server/routes/api/fileAvailability.js
@@ -0,0 +1,33 @@
+
+const { handleErrorResponse } = require('helpers/errorHandlers.js');
+
+/*
+
+  route to see if asset is available locally
+
+*/
+
+const fileAvailability = (db) => {
+  return ({ ip, originalUrl, params }, res) => {
+    const name = params.name;
+    const claimId = params.claimId;
+    db.File
+      .findOne({
+        where: {
+          name,
+          claimId,
+        },
+      })
+      .then(result => {
+        if (result) {
+          return res.status(200).json({success: true, data: true});
+        }
+        res.status(200).json({success: true, data: false});
+      })
+      .catch(error => {
+        handleErrorResponse(originalUrl, ip, error, res);
+      });
+  };
+};
+
+module.exports = fileAvailability;
diff --git a/server/routes/api/index.js b/server/routes/api/index.js
new file mode 100644
index 00000000..5d141163
--- /dev/null
+++ b/server/routes/api/index.js
@@ -0,0 +1,29 @@
+const channelAvailability = require('./channelAvailability');
+const channelClaims = require('./channelClaims');
+const channelData = require('./channelData');
+const channelShortId = require('./channelShortId');
+const claimAvailability = require('./claimAvailability');
+const claimData = require('./claimData');
+const claimGet = require('./claimGet');
+const claimLongId = require('./claimLongId');
+const claimPublish = require('./claimPublish');
+const claimResolve = require('./claimResolve');
+const claimShortId = require('./claimShortId');
+const claimsList = require('./claimsList');
+const fileAvailability = require('./fileAvailability');
+
+module.exports = {
+  channelAvailability,
+  channelClaims,
+  channelData,
+  channelShortId,
+  claimAvailability,
+  claimData,
+  claimGet,
+  claimLongId,
+  claimPublish,
+  claimResolve,
+  claimShortId,
+  claimsList,
+  fileAvailability,
+};
diff --git a/server/routes/apiRoutes/index.js b/server/routes/apiRoutes/index.js
deleted file mode 100644
index 2dee4c3c..00000000
--- a/server/routes/apiRoutes/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const channelShortId = require('./channelShortId');
-
-module.exports = {
-  channelShortId,
-}
diff --git a/server/routes/apiRoutes/otherRoutes.js b/server/routes/apiRoutes/otherRoutes.js
deleted file mode 100644
index 459388de..00000000
--- a/server/routes/apiRoutes/otherRoutes.js
+++ /dev/null
@@ -1,232 +0,0 @@
-const logger = require('winston');
-const { details: { host } } = require('../../../config/siteConfig.js');
-const { db } = require('../../../config/mysqlConfig.js');
-const { claimNameIsAvailable, checkChannelAvailability, publish } = require('../../controllers/publishController.js');
-const { getClaimList, resolveUri, getClaim } = require('../../helpers/lbryApi.js');
-const { addGetResultsToFileData, createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles, createFileData } = require('../../helpers/publishHelpers.js');
-const errorHandlers = require('../../helpers/errorHandlers.js');
-const { sendGATimingEvent } = require('../../helpers/googleAnalytics.js');
-const { authenticateUser } = require('../../auth/authentication.js');
-const { getChannelData, getChannelClaims, getClaimId } = require('../../controllers/serveController.js');
-
-const NO_CHANNEL = 'NO_CHANNEL';
-const NO_CLAIM = 'NO_CLAIM';
-
-const routes = {
-  // route to check whether site has published to a channel
-  channelAvailabilityRoute ({ ip, originalUrl, params: { name } }, res) {
-    const gaStartTime = Date.now();
-    checkChannelAvailability(name)
-      .then(availableName => {
-        res.status(200).json(availableName);
-        sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  channelDataRoute ({ ip, originalUrl, body, params }, res) {
-    const channelName = params.channelName;
-    let channelClaimId = params.channelClaimId;
-    if (channelClaimId === 'none') channelClaimId = null;
-    getChannelData(channelName, channelClaimId, 0)
-      .then(data => {
-        if (data === NO_CHANNEL) {
-          return res.status(404).json({success: false, message: 'No matching channel was found'});
-        }
-        res.status(200).json({success: true, data});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  channelClaimsRoute ({ ip, originalUrl, body, params }, res) {
-    const channelName = params.channelName;
-    let channelClaimId = params.channelClaimId;
-    if (channelClaimId === 'none') channelClaimId = null;
-    const page = params.page;
-    getChannelClaims(channelName, channelClaimId, page)
-      .then(data => {
-        if (data === NO_CHANNEL) {
-          return res.status(404).json({success: false, message: 'No matching channel was found'});
-        }
-        res.status(200).json({success: true, data});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to run a claim_list request on the daemon
-  claimListRoute ({ ip, originalUrl, params }, res) {
-    getClaimList(params.name)
-      .then(claimsList => {
-        res.status(200).json(claimsList);
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to get an asset
-  claimGetRoute ({ ip, originalUrl, params }, res) {
-    const name = params.name;
-    const claimId = params.claimId;
-    // resolve the claim
-    db.Claim.resolveClaim(name, claimId)
-      .then(resolveResult => {
-        // make sure a claim actually exists at that uri
-        if (!resolveResult) {
-          throw new Error('No matching uri found in Claim table');
-        }
-        let fileData = createFileData(resolveResult);
-        // get the claim
-        return Promise.all([fileData, getClaim(`${name}#${claimId}`)]);
-      })
-      .then(([ fileData, getResult ]) => {
-        fileData = addGetResultsToFileData(fileData, getResult);
-        return Promise.all([db.upsert(db.File, fileData, {name, claimId}, 'File'), getResult]);
-      })
-      .then(([ fileRecord, {message, completed} ]) => {
-        res.status(200).json({ success: true, message, completed });
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to check whether this site published to a claim
-  claimAvailabilityRoute ({ ip, originalUrl, params: { name } }, res) {
-    const gaStartTime = Date.now();
-    claimNameIsAvailable(name)
-      .then(result => {
-        res.status(200).json(result);
-        sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to run a resolve request on the daemon
-  claimResolveRoute ({ headers, ip, originalUrl, params }, res) {
-    resolveUri(`${params.name}#${params.claimId}`)
-      .then(resolvedUri => {
-        res.status(200).json(resolvedUri);
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to run a publish request on the daemon
-  claimPublishRoute ({ body, files, headers, ip, originalUrl, user }, res) {
-    // define variables
-    let  channelName, channelId, channelPassword, description, fileName, filePath, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title;
-    // record the start time of the request
-    gaStartTime = Date.now();
-    // validate the body and files of the request
-    try {
-      // validateApiPublishRequest(body, files);
-      ({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body));
-      ({fileName, filePath, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files));
-      ({channelName, channelId, channelPassword} = body);
-    } catch (error) {
-      return res.status(400).json({success: false, message: error.message});
-    }
-    // check channel authorization
-    Promise.all([
-      authenticateUser(channelName, channelId, channelPassword, user),
-      claimNameIsAvailable(name),
-      createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail),
-      createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw),
-    ])
-      .then(([{channelName, channelClaimId}, validatedClaimName, publishParams, thumbnailPublishParams]) => {
-        // add channel details to the publish params
-        if (channelName && channelClaimId) {
-          publishParams['channel_name'] = channelName;
-          publishParams['channel_id'] = channelClaimId;
-        }
-        // publish the thumbnail
-        if (thumbnailPublishParams) {
-          publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);
-        }
-        // publish the asset
-        return publish(publishParams, fileName, fileType);
-      })
-      .then(result => {
-        res.status(200).json({
-          success: true,
-          message: 'publish completed successfully',
-          data   : {
-            name,
-            claimId: result.claim_id,
-            url    : `${host}/${result.claim_id}/${name}`,
-            lbryTx : result,
-          },
-        });
-        // record the publish end time and send to google analytics
-        sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to get a short claim id from long claim Id
-  claimShortIdRoute ({ ip, originalUrl, body, params }, res) {
-    db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)
-      .then(shortId => {
-        res.status(200).json({success: true, data: shortId});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  claimLongIdRoute ({ ip, originalUrl, body, params }, res) {
-    logger.debug('body:', body);
-    const channelName = body.channelName;
-    const channelClaimId = body.channelClaimId;
-    const claimName = body.claimName;
-    const claimId = body.claimId;
-    getClaimId(channelName, channelClaimId, claimName, claimId)
-      .then(result => {
-        if (result === NO_CHANNEL) {
-          return res.status(404).json({success: false, message: 'No matching channel could be found'});
-        }
-        if (result === NO_CLAIM) {
-          return res.status(404).json({success: false, message: 'No matching claim id could be found'});
-        }
-        res.status(200).json({success: true, data: result});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  claimDataRoute ({ ip, originalUrl, body, params }, res) {
-    const claimName = params.claimName;
-    let claimId = params.claimId;
-    if (claimId === 'none') claimId = null;
-    db.Claim.resolveClaim(claimName, claimId)
-      .then(claimInfo => {
-        if (!claimInfo) {
-          return res.status(404).json({success: false, message: 'No claim could be found'});
-        }
-        res.status(200).json({success: true, data: claimInfo});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-  // route to see if asset is available locally
-  fileAvailabilityRoute ({ ip, originalUrl, params }, res) {
-    const name = params.name;
-    const claimId = params.claimId;
-    db.File.findOne({where: {name, claimId}})
-      .then(result => {
-        if (result) {
-          return res.status(200).json({success: true, data: true});
-        }
-        res.status(200).json({success: true, data: false});
-      })
-      .catch(error => {
-        errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
-      });
-  },
-};
-
-module.exports = routes;
diff --git a/server/routes/asset/index.js b/server/routes/asset/index.js
new file mode 100644
index 00000000..d988c234
--- /dev/null
+++ b/server/routes/asset/index.js
@@ -0,0 +1,8 @@
+const serveAssetByClaim = require('./serveAssetByClaim');
+const serveAssetByIdentifierAndClaim = require('./serveAssetByIdentifierAndClaim');
+
+
+module.exports = {
+  serveAssetByClaim,
+  serveAssetByIdentifierAndClaim,
+};
diff --git a/server/routes/asset/serveAssetByClaim.js b/server/routes/asset/serveAssetByClaim.js
new file mode 100644
index 00000000..4585c1e7
--- /dev/null
+++ b/server/routes/asset/serveAssetByClaim.js
@@ -0,0 +1,44 @@
+const { sendGAServeEvent } = require('../../helpers/googleAnalytics');
+const { determineResponseType, logRequestData, getClaimIdAndServeAsset } = require('../../helpers/serveHelpers.js');
+const lbryUri = require('../../helpers/lbryUri.js');
+const handleShowRender = require('../../helpers/handleShowRender.jsx');
+const SERVE = 'SERVE';
+
+/*
+
+  route to serve an asset or the react app via the claim name only
+
+*/
+
+const claim = () => {
+  return (req, res) => {
+    const { headers, ip, originalUrl, params } = req;
+    // decide if this is a show request
+    let hasFileExtension;
+    try {
+      ({ hasFileExtension } = lbryUri.parseModifier(params.claim));
+    } catch (error) {
+      return res.status(400).json({success: false, message: error.message});
+    }
+    let responseType = determineResponseType(hasFileExtension, headers);
+    if (responseType !== SERVE) {
+      return handleShowRender(req, res);
+    }
+    // handle serve request
+    // send google analytics
+    sendGAServeEvent(headers, ip, originalUrl);
+    // parse the claim
+    let claimName;
+    try {
+      ({claimName} = lbryUri.parseClaim(params.claim));
+    } catch (error) {
+      return res.status(400).json({success: false, message: error.message});
+    }
+    // log the request data for debugging
+    logRequestData(responseType, claimName, null, null);
+    // get the claim Id and then serve the asset
+    getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);
+  };
+};
+
+module.exports = claim;
diff --git a/server/routes/asset-routes.js b/server/routes/asset/serveAssetByIdentifierAndClaim.js
similarity index 52%
rename from server/routes/asset-routes.js
rename to server/routes/asset/serveAssetByIdentifierAndClaim.js
index 5096885d..258780bf 100644
--- a/server/routes/asset-routes.js
+++ b/server/routes/asset/serveAssetByIdentifierAndClaim.js
@@ -1,12 +1,18 @@
-const { sendGAServeEvent } = require('../helpers/googleAnalytics');
-const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset } = require('../helpers/serveHelpers.js');
-const lbryUri = require('../helpers/lbryUri.js');
-const handleShowRender = require('../helpers/handleShowRender.jsx');
+const { sendGAServeEvent } = require('../../helpers/googleAnalytics');
+const { determineResponseType, flipClaimNameAndIdForBackwardsCompatibility, logRequestData, getClaimIdAndServeAsset } = require('../../helpers/serveHelpers.js');
+const lbryUri = require('../../helpers/lbryUri.js');
+const handleShowRender = require('../../helpers/handleShowRender.jsx');
+
 const SERVE = 'SERVE';
 
-module.exports = (app) => {
-  // route to serve a specific asset using the channel or claim id
-  app.get('/:identifier/:claim', (req, res) => {
+/*
+
+  route to serve an asset or the react app via the claim name and an identifier
+
+*/
+
+const identifierClaim = () => {
+  return (req, res) => {
     const { headers, ip, originalUrl, params } = req;
     // decide if this is a show request
     let hasFileExtension;
@@ -43,34 +49,7 @@ module.exports = (app) => {
     logRequestData(responseType, claimName, channelName, claimId);
     // get the claim Id and then serve the asset
     getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);
-  });
-  // route to serve the winning asset at a claim or a channel page
-  app.get('/:claim', (req, res) => {
-    const { headers, ip, originalUrl, params } = req;
-    // decide if this is a show request
-    let hasFileExtension;
-    try {
-      ({ hasFileExtension } = lbryUri.parseModifier(params.claim));
-    } catch (error) {
-      return res.status(400).json({success: false, message: error.message});
-    }
-    let responseType = determineResponseType(hasFileExtension, headers);
-    if (responseType !== SERVE) {
-      return handleShowRender(req, res);
-    }
-    // handle serve request
-    // send google analytics
-    sendGAServeEvent(headers, ip, originalUrl);
-    // parse the claim
-    let claimName;
-    try {
-      ({claimName} = lbryUri.parseClaim(params.claim));
-    } catch (error) {
-      return res.status(400).json({success: false, message: error.message});
-    }
-    // log the request data for debugging
-    logRequestData(responseType, claimName, null, null);
-    // get the claim Id and then serve the asset
-    getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);
-  });
+  };
 };
+
+module.exports = identifierClaim;
diff --git a/server/routes/auth-routes.js b/server/routes/auth/auth-routes.js
similarity index 100%
rename from server/routes/auth-routes.js
rename to server/routes/auth/auth-routes.js
diff --git a/server/routes/fallback-routes.js b/server/routes/fallback/fallback-routes.js
similarity index 72%
rename from server/routes/fallback-routes.js
rename to server/routes/fallback/fallback-routes.js
index 9034b4a8..01d1e7f0 100644
--- a/server/routes/fallback-routes.js
+++ b/server/routes/fallback/fallback-routes.js
@@ -1,4 +1,4 @@
-const handlePageRender = require('../helpers/handlePageRender.jsx');
+const handlePageRender = require('../../helpers/handlePageRender.jsx');
 
 module.exports = app => {
   // a catch-all route if someone visits a page that does not exist
diff --git a/server/routes/page-routes.js b/server/routes/page/page-routes.js
similarity index 87%
rename from server/routes/page-routes.js
rename to server/routes/page/page-routes.js
index 44c19be1..6bbdafa3 100644
--- a/server/routes/page-routes.js
+++ b/server/routes/page/page-routes.js
@@ -1,5 +1,5 @@
-const { details: host } = require('../../config/siteConfig.js');
-const handlePageRender = require('../helpers/handlePageRender.jsx');
+const { details: host } = require('../../../config/siteConfig.js');
+const handlePageRender = require('../../helpers/handlePageRender.jsx');
 
 module.exports = (app) => {
   // route for the home page
diff --git a/speech.js b/speech.js
index bae7ecfe..5b879159 100644
--- a/speech.js
+++ b/speech.js
@@ -1,4 +1,5 @@
-const apiRoutes = require('./server/routes/apiRoutes/');
+const api = require('./server/routes/api/');
+const asset = require('./server/routes/asset/');
 const logger = require('./config/loggerConfig.js');
 const mysql = require('./config/mysqlConfig');
 const site = require('./config/siteConfig');
@@ -8,13 +9,16 @@ const models = require('./server/models/');
 // const Components = require('./client/components');
 
 const exports = {
-  apiRoutes,
   logger,
+  models,
   mysql,
+  passport,
   site,
   slack,
-  passport,
-  models,
+  routes: {
+    api,
+    asset,
+  },
   // Components,
 };