diff --git a/helpers/lbryUri.js b/helpers/lbryUri.js
index 15ab0b86..f72a25ef 100644
--- a/helpers/lbryUri.js
+++ b/helpers/lbryUri.js
@@ -55,14 +55,14 @@ module.exports = {
claimId,
};
},
- parseName: function (name) {
- logger.debug('parsing name:', name);
+ parseClaim: function (claim) {
+ logger.debug('parsing name:', claim);
const componentsRegex = new RegExp(
'([^:$#/.]*)' + // name (stops at the first modifier)
'([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
);
const [proto, claimName, modifierSeperator, modifier] = componentsRegex
- .exec(name)
+ .exec(claim)
.map(match => match || null);
logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);
@@ -75,7 +75,6 @@ module.exports = {
throw new Error(`Invalid characters in claim name: ${nameBadChars.join(', ')}.`);
}
// Validate and process modifier
- let isServeRequest = false;
if (modifierSeperator) {
if (!modifier) {
throw new Error(`No file extension provided after separator ${modifierSeperator}.`);
@@ -83,11 +82,29 @@ module.exports = {
if (modifierSeperator !== '.') {
throw new Error(`The ${modifierSeperator} modifier is not supported in the claim name`);
}
- isServeRequest = true;
}
+ // return results
return {
claimName,
- isServeRequest,
+ };
+ },
+ parseModifier: function (claim) {
+ logger.debug('parsing modifier:', claim);
+ const componentsRegex = new RegExp(
+ '([^:$#/.]*)' + // name (stops at the first modifier)
+ '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
+ );
+ const [proto, claimName, modifierSeperator, modifier] = componentsRegex
+ .exec(claim)
+ .map(match => match || null);
+ logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);
+ // Validate and process modifier
+ let hasFileExtension = false;
+ if (modifierSeperator) {
+ hasFileExtension = true;
+ }
+ return {
+ hasFileExtension,
};
},
};
diff --git a/react/components/AssetDisplay/index.js b/react/components/AssetDisplay/index.js
index 18d72c12..ae630a0b 100644
--- a/react/components/AssetDisplay/index.js
+++ b/react/components/AssetDisplay/index.js
@@ -1,9 +1,9 @@
import React from 'react';
-const AssetDisplay = ({ claimName, claimId }) => {
+const AssetDisplay = ({ name, claimId }) => {
return (
-
display {claimName}#{claimId} here
+
display {name}#{claimId} here
);
};
diff --git a/react/components/AssetInfo/index.js b/react/components/AssetInfo/index.js
index 4c0306aa..006ea701 100644
--- a/react/components/AssetInfo/index.js
+++ b/react/components/AssetInfo/index.js
@@ -54,7 +54,7 @@ class AssetInfo extends React.Component {
@@ -114,13 +114,13 @@ class AssetInfo extends React.Component {
twitter
+ href={`https://twitter.com/intent/tweet?text=${this.props.host}/${this.props.shortClaimId}/${this.props.name}`}>twitter
facebook
+ href={`https://www.facebook.com/sharer/sharer.php?u=${this.props.host}/${this.props.shortClaimId}/${this.props.name}`}>facebook
tumblr
+ href={`http://tumblr.com/widgets/share/tool?canonicalUrl=${this.props.host}/${this.props.shortClaimId}/${this.props.name}`}>tumblr
reddit
+ href={`https://www.reddit.com/submit?url=${this.props.host}/${this.props.shortClaimId}/${this.props.name}&title=${this.props.name}`}>reddit
@@ -168,6 +168,6 @@ class AssetInfo extends React.Component {
};
// required props
-// {channelName, certificateId, description, shortId, name, fileExt, claimId, contentType, thumbnail, host}
+// {channelName, certificateId, description, shortClaimId, name, fileExt, claimId, contentType, thumbnail, host}
export default AssetInfo;
diff --git a/react/components/ErrorPage/index.js b/react/components/ErrorPage/index.js
new file mode 100644
index 00000000..f40d348a
--- /dev/null
+++ b/react/components/ErrorPage/index.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import NavBar from 'containers/NavBar';
+
+class ErrorPage extends React.Component {
+ render () {
+ return (
+
+ );
+ }
+};
+
+// required props
+// error
+
+export default ErrorPage;
diff --git a/react/components/ShowAsset/index.js b/react/components/ShowAsset/index.js
index d2dd5db7..616ae44e 100644
--- a/react/components/ShowAsset/index.js
+++ b/react/components/ShowAsset/index.js
@@ -1,6 +1,6 @@
import React from 'react';
-import ShowLite from 'components/ShowAssetLite';
-import ShowDetails from 'components/ShowAssetDetails';
+import ShowAssetLite from 'components/ShowAssetLite';
+import ShowAssetDetails from 'components/ShowAssetDetails';
import request from 'utils/request';
class ShowAsset extends React.Component {
@@ -83,14 +83,14 @@ class ShowAsset extends React.Component {
render () {
if (this.props.isServeRequest) {
return (
-
);
}
return (
-
diff --git a/react/components/ShowAssetDetails/index.js b/react/components/ShowAssetDetails/index.js
index a6e810bb..640aa409 100644
--- a/react/components/ShowAssetDetails/index.js
+++ b/react/components/ShowAssetDetails/index.js
@@ -13,7 +13,9 @@ class ShowDetails extends React.Component {
{this.props.error &&
-
{this.props.error}
+
}
{this.props.claimData &&
@@ -23,13 +25,24 @@ class ShowDetails extends React.Component {
diff --git a/react/components/ShowPage/index.js b/react/components/ShowPage/index.js
index 6945e729..67e6a68e 100644
--- a/react/components/ShowPage/index.js
+++ b/react/components/ShowPage/index.js
@@ -1,4 +1,5 @@
import React from 'react';
+import ErrorPage from 'components/ErrorPage';
import ShowAsset from 'components/ShowAsset';
import ShowChannel from 'components/ShowChannel';
import lbryUri from 'utils/lbryUri';
@@ -10,6 +11,7 @@ class ShowPage extends React.Component {
constructor (props) {
super(props);
this.state = {
+ error : null,
identifier : null,
claim : null,
isServeRequest: null,
@@ -46,9 +48,9 @@ class ShowPage extends React.Component {
let isChannel, channelName, channelClaimId, claimId, claimName, isServeRequest;
try {
({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(identifier));
- ({ claimName, isServeRequest } = lbryUri.parseName(claim));
+ ({ claimName, isServeRequest } = lbryUri.parseClaim(claim));
} catch (error) {
- return console.log('error:', error);
+ return this.setState({error: error.message});
}
// set state
return this.setState({
@@ -72,7 +74,7 @@ class ShowPage extends React.Component {
try {
({ isChannel, channelName, channelClaimId } = lbryUri.parseIdentifier(claim));
} catch (error) {
- return console.log('error:', error);
+ return this.setState({error: error.message});
}
if (isChannel) {
return this.setState({
@@ -85,9 +87,9 @@ class ShowPage extends React.Component {
}
let claimName, isServeRequest;
try {
- ({claimName, isServeRequest} = lbryUri.parseName(claim));
+ ({claimName, isServeRequest} = lbryUri.parseClaim(claim));
} catch (error) {
- return console.log('error:', error);
+ return this.setState({error: error.message});
}
this.setState({
claim: {
@@ -98,6 +100,11 @@ class ShowPage extends React.Component {
}
render () {
console.log('rendering ShowPage');
+ if (this.state.error) {
+ return (
+
+ );
+ }
if (this.state.claim) {
if (this.state.claim.isChannel) {
return (
diff --git a/react/utils/lbryUri.js b/react/utils/lbryUri.js
index 653b0fe7..957a1a5f 100644
--- a/react/utils/lbryUri.js
+++ b/react/utils/lbryUri.js
@@ -16,18 +16,18 @@ module.exports = {
// Validate and process name
if (!value) {
- throw new Error(`Check your url. No channel name provided before "${modifierSeperator}"`);
+ throw new Error(`Check your URL. No channel name provided before "${modifierSeperator}"`);
}
const isChannel = value.startsWith(module.exports.CHANNEL_CHAR);
const channelName = isChannel ? value : null;
let claimId;
if (isChannel) {
if (!channelName) {
- throw new Error('No channel name after @.');
+ throw new Error('Check your URL. No channel name after "@".');
}
const nameBadChars = (channelName).match(module.exports.REGEXP_INVALID_CHANNEL);
if (nameBadChars) {
- throw new Error(`Invalid characters in channel name: ${nameBadChars.join(', ')}.`);
+ throw new Error(`Check your URL. Invalid characters in channel name: "${nameBadChars.join(', ')}".`);
}
} else {
claimId = value;
@@ -37,13 +37,13 @@ module.exports = {
let channelClaimId;
if (modifierSeperator) {
if (!modifier) {
- throw new Error(`No modifier provided after separator "${modifierSeperator}"`);
+ throw new Error(`Check your URL. No modifier provided after separator "${modifierSeperator}"`);
}
if (modifierSeperator === ':') {
channelClaimId = modifier;
} else {
- throw new Error(`The "${modifierSeperator}" modifier is not currently supported`);
+ throw new Error(`Check your URL. The "${modifierSeperator}" modifier is not currently supported`);
}
}
return {
@@ -53,7 +53,7 @@ module.exports = {
claimId,
};
},
- parseName: function (name) {
+ parseClaim: function (name) {
console.log('parsing name:', name);
const componentsRegex = new RegExp(
'([^:$#/.]*)' + // name (stops at the first modifier)
@@ -66,20 +66,20 @@ module.exports = {
// Validate and process name
if (!claimName) {
- throw new Error('No claim name provided before .');
+ throw new Error('Check your URL. No claim name provided before "."');
}
const nameBadChars = (claimName).match(module.exports.REGEXP_INVALID_CLAIM);
if (nameBadChars) {
- throw new Error(`Invalid characters in claim name: ${nameBadChars.join(', ')}.`);
+ throw new Error(`Check your URL. Invalid characters in claim name: "${nameBadChars.join(', ')}".`);
}
// Validate and process modifier
let isServeRequest = false;
if (modifierSeperator) {
if (!modifier) {
- throw new Error(`No file extension provided after separator ${modifierSeperator}.`);
+ throw new Error(`Check your URL. No file extension provided after separator "${modifierSeperator}".`);
}
if (modifierSeperator !== '.') {
- throw new Error(`The ${modifierSeperator} modifier is not supported in the claim name`);
+ throw new Error(`Check your URL. The "${modifierSeperator}" modifier is not supported in the claim name.`);
}
isServeRequest = true;
}
diff --git a/routes/serve-routes.js b/routes/serve-routes.js
index ab42137e..b95c564a 100644
--- a/routes/serve-routes.js
+++ b/routes/serve-routes.js
@@ -2,13 +2,10 @@ const logger = require('winston');
const { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');
const serveHelpers = require('../helpers/serveHelpers.js');
const { handleRequestError } = require('../helpers/errorHandlers.js');
-const { postToStats } = require('../helpers/statsHelpers.js');
-const db = require('../models');
const lbryUri = require('../helpers/lbryUri.js');
const SERVE = 'SERVE';
const SHOW = 'SHOW';
-const SHOWLITE = 'SHOWLITE';
const NO_CHANNEL = 'NO_CHANNEL';
const NO_CLAIM = 'NO_CLAIM';
const NO_FILE = 'NO_FILE';
@@ -39,49 +36,23 @@ function clientWantsAsset ({accept, range}) {
return imageIsWanted || videoIsWanted;
}
-function determineResponseType (isServeRequest, headers) {
+function determineResponseType (hasFileExtension, headers) {
let responseType;
- if (isServeRequest) {
- responseType = SERVE;
- if (clientAcceptsHtml(headers)) { // this is in case a serve request comes from a browser
- responseType = SHOWLITE;
+ if (hasFileExtension) {
+ responseType = SERVE; // assume a serve request if file extension is present
+ if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request
+ responseType = SHOW;
}
} else {
responseType = SHOW;
if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url
- logger.debug('Show request came from browser and wants an image/video; changing response to serve.');
+ logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');
responseType = SERVE;
}
}
return responseType;
}
-// function showAssetToClient (claimId, name, res) {
-// return Promise
-// .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
-// .then(([claimInfo, shortClaimId]) => {
-// // logger.debug('claimInfo:', claimInfo);
-// // logger.debug('shortClaimId:', shortClaimId);
-// return serveHelpers.showFile(claimInfo, shortClaimId, res);
-// })
-// .catch(error => {
-// throw error;
-// });
-// }
-//
-// function showLiteAssetToClient (claimId, name, res) {
-// return Promise
-// .all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
-// .then(([claimInfo, shortClaimId]) => {
-// // logger.debug('claimInfo:', claimInfo);
-// // logger.debug('shortClaimId:', shortClaimId);
-// return serveHelpers.showFileLite(claimInfo, shortClaimId, res);
-// })
-// .catch(error => {
-// throw error;
-// });
-// }
-
function serveAssetToClient (claimId, name, res) {
return getLocalFileRecord(claimId, name)
.then(fileInfo => {
@@ -115,82 +86,87 @@ function logRequestData (responseType, claimName, channelName, claimId) {
module.exports = (app) => {
// route to serve a specific asset using the channel or claim id
- app.get('/:identifier/:name', ({ headers, ip, originalUrl, params }, res) => {
- let isChannel, channelName, channelClaimId, claimId, claimName, isServeRequest;
+ app.get('/:identifier/:claim', ({ headers, ip, originalUrl, params }, res) => {
+ // decide if this is a show request
+ let hasFileExtension;
+ try {
+ ({ hasFileExtension } = lbryUri.parseModifier(params.claim));
+ } catch (error) {
+ return res.status(200).json({success: false, message: error.message});
+ }
+ let responseType = determineResponseType(hasFileExtension, headers);
+ if (responseType !== SERVE) {
+ return res.status(200).render('index');
+ }
+ // parse the claim
+ let claimName;
+ try {
+ ({ claimName } = lbryUri.parseClaim(params.claim));
+ } catch (error) {
+ return res.status(200).json({success: false, message: error.message});
+ }
+ // parse the identifier
+ let isChannel, channelName, channelClaimId, claimId;
try {
({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(params.identifier));
- ({ claimName, isServeRequest } = lbryUri.parseName(params.name));
} catch (error) {
return handleRequestError(originalUrl, ip, error, res);
}
if (!isChannel) {
[claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);
}
- let responseType = determineResponseType(isServeRequest, headers);
// log the request data for debugging
logRequestData(responseType, claimName, channelName, claimId);
- // if a serve request, serve, otherwise send the react app
- if (responseType === SERVE) {
- // get the claim Id and then serve/show the asset
- getClaimId(channelName, channelClaimId, claimName, claimId)
- .then(fullClaimId => {
- if (fullClaimId === NO_CLAIM) {
- return res.status(200).json({success: false, message: 'no claim id could be found'});
- } else if (fullClaimId === NO_CHANNEL) {
- return res.status(200).json({success: false, message: 'no channel id could be found'});
- }
- serveAssetToClient(fullClaimId, claimName, res);
- // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
- })
- .catch(error => {
- handleRequestError(originalUrl, ip, error, res);
- // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
- });
- } else {
- res.status(200).render('index');
- }
+ // get the claim Id and then serve the asset
+ getClaimId(channelName, channelClaimId, claimName, claimId)
+ .then(fullClaimId => {
+ if (fullClaimId === NO_CLAIM) {
+ return res.status(200).json({success: false, message: 'no claim id could be found'});
+ } else if (fullClaimId === NO_CHANNEL) {
+ return res.status(200).json({success: false, message: 'no channel id could be found'});
+ }
+ serveAssetToClient(fullClaimId, claimName, res);
+ // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
+ })
+ .catch(error => {
+ handleRequestError(originalUrl, ip, error, res);
+ // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
+ });
});
// route to serve the winning asset at a claim or a channel page
- app.get('/:identifier', ({ headers, ip, originalUrl, params, query }, res) => {
- let isChannel, channelName, channelClaimId;
+ app.get('/:claim', ({ headers, ip, originalUrl, params, query }, res) => {
+ // decide if this is a show request
+ let hasFileExtension;
try {
- ({ isChannel, channelName, channelClaimId } = lbryUri.parseIdentifier(params.identifier));
- // log the result
- logger.debug(`isChannel: ${isChannel}, channelName: ${channelName}, channelClaimId: ${channelClaimId}`);
+ ({ hasFileExtension } = lbryUri.parseModifier(params.claim));
} catch (error) {
- return handleRequestError(originalUrl, ip, error, res);
+ return res.status(200).json({success: false, message: error.message});
}
- if (isChannel) {
- // handle showing the channel page
+ let responseType = determineResponseType(hasFileExtension, headers);
+ if (responseType !== SERVE) {
return res.status(200).render('index');
- } else {
- let claimName, isServeRequest;
- try {
- ({claimName, isServeRequest} = lbryUri.parseName(params.identifier));
- } catch (error) {
- return handleRequestError(originalUrl, ip, error, res);
- }
- let responseType = determineResponseType(isServeRequest, headers);
- // log the request data for debugging
- logRequestData(responseType, claimName, null, null);
- // if a serve request, serve, otherwise send the react app
- if (responseType === SERVE) {
- // get the claim Id and then serve/show the asset
- getClaimId(null, null, claimName, null)
- .then(fullClaimId => {
- if (fullClaimId === NO_CLAIM) {
- return res.status(200).render('index');
- }
- serveAssetToClient(fullClaimId, claimName, res);
- // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
- })
- .catch(error => {
- handleRequestError(originalUrl, ip, error, res);
- // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
- });
- } else {
- res.status(200).render('index');
- }
}
+ // parse the claim
+ let claimName;
+ try {
+ ({claimName} = lbryUri.parseClaim(params.claim));
+ } catch (error) {
+ return res.status(200).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
+ getClaimId(null, null, claimName, null)
+ .then(fullClaimId => {
+ if (fullClaimId === NO_CLAIM) {
+ return res.status(200).render('index');
+ }
+ serveAssetToClient(fullClaimId, claimName, res);
+ // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
+ })
+ .catch(error => {
+ handleRequestError(originalUrl, ip, error, res);
+ // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
+ });
});
};