diff --git a/client/build/utils/metaTags.js b/client/build/utils/metaTags.js index 34daa9e0..9713f663 100644 --- a/client/build/utils/metaTags.js +++ b/client/build/utils/metaTags.js @@ -101,9 +101,9 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) { defaultThumbnail = _ref3.defaultThumbnail; var claimData = asset.claimData; var contentType = claimData.contentType; - var embedUrl = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name); + var videoEmbedUrl = "".concat(siteHost, "/video-embed/").concat(claimData.name, "/").concat(claimData.claimId); var showUrl = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name); - var source = "".concat(siteHost, "/").concat(claimData.claimId, "/").concat(claimData.name, ".").concat(claimData.fileExt); + var source = "".concat(siteHost, "/asset/").concat(claimData.name, "/").concat(claimData.claimId); var ogTitle = claimData.title || claimData.name; var ogDescription = claimData.description || defaultDescription; var ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail); @@ -154,7 +154,7 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) { }); metaTags.push({ property: 'og:type', - content: 'video' + content: 'video.other' }); metaTags.push({ property: 'twitter:card', @@ -162,7 +162,7 @@ var createAssetMetaTags = function createAssetMetaTags(_ref3) { }); metaTags.push({ property: 'twitter:player', - content: embedUrl + content: videoEmbedUrl }); metaTags.push({ property: 'twitter:player:width', diff --git a/client/src/utils/metaTags.js b/client/src/utils/metaTags.js index cd11b853..c5b9df34 100644 --- a/client/src/utils/metaTags.js +++ b/client/src/utils/metaTags.js @@ -46,9 +46,9 @@ const createChannelMetaTags = ({siteHost, siteTitle, siteTwitter, channel}) => { const createAssetMetaTags = ({siteHost, siteTitle, siteTwitter, asset, defaultDescription, defaultThumbnail}) => { const { claimData } = asset; const { contentType } = claimData; - const embedUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`; + const videoEmbedUrl = `${siteHost}/video-embed/${claimData.name}/${claimData.claimId}`; const showUrl = `${siteHost}/${claimData.claimId}/${claimData.name}`; - const source = `${siteHost}/${claimData.claimId}/${claimData.name}.${claimData.fileExt}`; + const source = `${siteHost}/asset/${claimData.name}/${claimData.claimId}`; const ogTitle = claimData.title || claimData.name; const ogDescription = claimData.description || defaultDescription; const ogThumbnailContentType = determineOgThumbnailContentType(claimData.thumbnail); @@ -68,9 +68,9 @@ const createAssetMetaTags = ({siteHost, siteTitle, siteTwitter, asset, defaultDe metaTags.push({property: 'og:video:type', content: contentType}); metaTags.push({property: 'og:image', content: ogThumbnail}); metaTags.push({property: 'og:image:type', content: ogThumbnailContentType}); - metaTags.push({property: 'og:type', content: 'video'}); + metaTags.push({property: 'og:type', content: 'video.other'}); metaTags.push({property: 'twitter:card', content: 'player'}); - metaTags.push({property: 'twitter:player', content: embedUrl}); + metaTags.push({property: 'twitter:player', content: videoEmbedUrl}); metaTags.push({property: 'twitter:player:width', content: 600}); metaTags.push({property: 'twitter:text:player_width', content: 600}); metaTags.push({property: 'twitter:player:height', content: 337}); diff --git a/server/controllers/assets/constants/request_types.js b/server/controllers/assets/constants/request_types.js new file mode 100644 index 00000000..22f0d0ce --- /dev/null +++ b/server/controllers/assets/constants/request_types.js @@ -0,0 +1,9 @@ +const EMBED = 'EMBED'; +const BROWSER = 'BROWSER'; +const SOCIAL = 'SOCIAL'; + +module.exports = { + EMBED, + BROWSER, + SOCIAL, +}; diff --git a/server/controllers/assets/serveAsset/index.js b/server/controllers/assets/serveAsset/index.js new file mode 100644 index 00000000..3f0149a8 --- /dev/null +++ b/server/controllers/assets/serveAsset/index.js @@ -0,0 +1,17 @@ +const { sendGAServeEvent } = require('../../../utils/googleAnalytics'); +const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); + +/* + + route to serve an asset directly + +*/ + +const serveAsset = ({ headers, ip, originalUrl, params: { claimName, claimId } }, res) => { + // send google analytics + sendGAServeEvent(headers, ip, originalUrl); + // get the claim Id and then serve the asset + getClaimIdAndServeAsset(null, null, claimName, claimId, originalUrl, ip, res); +}; + +module.exports = serveAsset; diff --git a/server/controllers/assets/serveByClaim/index.js b/server/controllers/assets/serveByClaim/index.js index a561754e..6e0e9e40 100644 --- a/server/controllers/assets/serveByClaim/index.js +++ b/server/controllers/assets/serveByClaim/index.js @@ -3,11 +3,10 @@ const handleShowRender = require('../../../render/build/handleShowRender.js'); const lbryUri = require('../utils/lbryUri.js'); -const determineResponseType = require('../utils/determineResponseType.js'); +const determineRequestType = require('../utils/determineRequestType.js'); const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); -const logRequestData = require('../utils/logRequestData.js'); -const SERVE = 'SERVE'; +const { EMBED } = require('../constants/request_types.js'); /* @@ -15,7 +14,7 @@ const SERVE = 'SERVE'; */ -const serverAssetByClaim = (req, res) => { +const serveByClaim = (req, res) => { const { headers, ip, originalUrl, params } = req; // decide if this is a show request let hasFileExtension; @@ -24,13 +23,11 @@ const serverAssetByClaim = (req, res) => { } catch (error) { return res.status(400).json({success: false, message: error.message}); } - let responseType = determineResponseType(hasFileExtension, headers); - if (responseType !== SERVE) { + // determine request type + let requestType = determineRequestType(hasFileExtension, headers); + if (requestType !== EMBED) { return handleShowRender(req, res); } - // handle serve request - // send google analytics - sendGAServeEvent(headers, ip, originalUrl); // parse the claim let claimName; try { @@ -38,10 +35,10 @@ const serverAssetByClaim = (req, res) => { } catch (error) { return res.status(400).json({success: false, message: error.message}); } - // log the request data for debugging - logRequestData(responseType, claimName, null, null); + // send google analytics + sendGAServeEvent(headers, ip, originalUrl); // get the claim Id and then serve the asset getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res); }; -module.exports = serverAssetByClaim; +module.exports = serveByClaim; diff --git a/server/controllers/assets/serveByIdentifierAndClaim/index.js b/server/controllers/assets/serveByIdentifierAndClaim/index.js index e493e01e..609a1256 100644 --- a/server/controllers/assets/serveByIdentifierAndClaim/index.js +++ b/server/controllers/assets/serveByIdentifierAndClaim/index.js @@ -3,12 +3,11 @@ const handleShowRender = require('../../../render/build/handleShowRender.js'); const lbryUri = require('../utils/lbryUri.js'); -const determineResponseType = require('../utils/determineResponseType.js'); +const determineRequestType = require('../utils/determineRequestType.js'); const getClaimIdAndServeAsset = require('../utils/getClaimIdAndServeAsset.js'); const flipClaimNameAndId = require('../utils/flipClaimNameAndId.js'); -const logRequestData = require('../utils/logRequestData.js'); -const SERVE = 'SERVE'; +const { EMBED } = require('../constants/request_types.js'); /* @@ -16,22 +15,20 @@ const SERVE = 'SERVE'; */ -const serverAssetByIdentifierAndClaim = (req, res) => { +const serverByIdentifierAndClaim = (req, res) => { const { headers, ip, originalUrl, params } = req; - // decide if this is a show request + // parse 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) { + // determine request type + let requestType = determineRequestType(hasFileExtension, headers); + if (requestType !== EMBED) { return handleShowRender(req, res); } - // handle serve request - // send google analytics - sendGAServeEvent(headers, ip, originalUrl); // parse the claim let claimName; try { @@ -50,10 +47,10 @@ const serverAssetByIdentifierAndClaim = (req, res) => { if (!isChannel) { [claimId, claimName] = flipClaimNameAndId(claimId, claimName); } - // log the request data for debugging - logRequestData(responseType, claimName, channelName, claimId); + // send google analytics + sendGAServeEvent(headers, ip, originalUrl); // get the claim Id and then serve the asset getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res); }; -module.exports = serverAssetByIdentifierAndClaim; +module.exports = serverByIdentifierAndClaim; diff --git a/server/controllers/assets/utils/determineRequestType.js b/server/controllers/assets/utils/determineRequestType.js new file mode 100644 index 00000000..4d3ce450 --- /dev/null +++ b/server/controllers/assets/utils/determineRequestType.js @@ -0,0 +1,54 @@ +const logger = require('winston'); +const { EMBED, BROWSER, SOCIAL } = require('../constants/request_types.js'); + +function headersMatchesSocialBotList (headers) { + const userAgent = headers['user-agent']; + const socialBotList = { + 'facebookexternalhit': 1, + 'Twitterbot' : 1, + }; + return socialBotList[userAgent]; +} + +function clientAcceptsHtml ({accept}) { + return accept && accept.match(/text\/html/); +}; + +function requestIsFromBrowser (headers) { + return headers['user-agent'] && headers['user-agent'].match(/Mozilla/); +}; + +function clientWantsAsset ({accept, range}) { + const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/); + const videoIsWanted = accept && range; + return imageIsWanted || videoIsWanted; +}; + +const determineRequestType = (hasFileExtension, headers) => { + let responseType; + logger.debug('headers:', headers); + // return early with 'show' if headers match the list + if (headersMatchesSocialBotList(headers)) { + return SOCIAL; + } + // if request is not from a social bot... + if (hasFileExtension) { + // assume embed, + responseType = EMBED; + // but change to browser if client accepts html. + if (clientAcceptsHtml(headers)) { + responseType = BROWSER; + } + // if request does not have file extentsion... + } else { + // assume browser, + responseType = BROWSER; + // but change to embed if someone embeded a show url... + if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { + responseType = EMBED; + } + } + return responseType; +}; + +module.exports = determineRequestType; diff --git a/server/controllers/assets/utils/determineResponseType.js b/server/controllers/assets/utils/determineResponseType.js deleted file mode 100644 index f32a0c5c..00000000 --- a/server/controllers/assets/utils/determineResponseType.js +++ /dev/null @@ -1,37 +0,0 @@ -const logger = require('winston'); - -const SERVE = 'SERVE'; -const SHOW = 'SHOW'; - -function clientAcceptsHtml ({accept}) { - return accept && accept.match(/text\/html/); -}; - -function requestIsFromBrowser (headers) { - return headers['user-agent'] && headers['user-agent'].match(/Mozilla/); -}; - -function clientWantsAsset ({accept, range}) { - const imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/); - const videoIsWanted = accept && range; - return imageIsWanted || videoIsWanted; -}; - -const determineResponseType = (hasFileExtension, headers) => { - let responseType; - 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 but wants an image/video. Changing response to serve...'); - responseType = SERVE; - } - } - return responseType; -}; - -module.exports = determineResponseType; diff --git a/server/controllers/assets/utils/getClaimIdAndServeAsset.js b/server/controllers/assets/utils/getClaimIdAndServeAsset.js index e391383d..83c4c770 100644 --- a/server/controllers/assets/utils/getClaimIdAndServeAsset.js +++ b/server/controllers/assets/utils/getClaimIdAndServeAsset.js @@ -17,6 +17,7 @@ const getClaimIdAndServeAsset = (channelName, channelClaimId, claimName, claimId getClaimId(channelName, channelClaimId, claimName, claimId) .then(fullClaimId => { claimId = fullClaimId; + logger.debug('FULL CLAIM ID:', fullClaimId); return db.Blocked.isNotBlocked(fullClaimId, claimName); }) .then(() => { diff --git a/server/controllers/pages/sendEmbedPage.js b/server/controllers/pages/sendVideoEmbedPage.js similarity index 73% rename from server/controllers/pages/sendEmbedPage.js rename to server/controllers/pages/sendVideoEmbedPage.js index d4bef437..01f6b1f4 100644 --- a/server/controllers/pages/sendEmbedPage.js +++ b/server/controllers/pages/sendVideoEmbedPage.js @@ -1,10 +1,10 @@ const { details: { host } } = require('@config/siteConfig'); -const sendEmbedPage = ({ params }, res) => { +const sendVideoEmbedPage = ({ params }, res) => { const claimId = params.claimId; const name = params.name; // get and render the content res.status(200).render('embed', { layout: 'embed', host, claimId, name }); }; -module.exports = sendEmbedPage; +module.exports = sendVideoEmbedPage; diff --git a/server/routes/api/index.js b/server/routes/api/index.js index 05c4973c..6a89348d 100644 --- a/server/routes/api/index.js +++ b/server/routes/api/index.js @@ -29,7 +29,7 @@ module.exports = (app) => { app.get('/api/claim/data/:claimName/:claimId', claimData); app.get('/api/claim/get/:name/:claimId', claimGet); app.get('/api/claim/list/:name', claimList); - app.post('/api/claim/long-id', claimLongId); + app.post('/api/claim/long-id', claimLongId); // should be a get app.post('/api/claim/publish', multipartMiddleware, claimPublish); app.get('/api/claim/resolve/:name/:claimId', claimResolve); app.get('/api/claim/short-id/:longId/:name', claimShortId); diff --git a/server/routes/assets/index.js b/server/routes/assets/index.js index 4e87d2dd..5d4f92d1 100644 --- a/server/routes/assets/index.js +++ b/server/routes/assets/index.js @@ -1,7 +1,9 @@ -const serveAssetByClaim = require('../../controllers/assets/serveByClaim'); -const serveAssetByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim'); +const serveByClaim = require('../../controllers/assets/serveByClaim'); +const serveByIdentifierAndClaim = require('../../controllers/assets/serveByIdentifierAndClaim'); +const serveAsset = require('../../controllers/assets/serveAsset'); -module.exports = (app, db) => { - app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim); - app.get('/:claim', serveAssetByClaim); +module.exports = (app) => { + app.get('/asset/:claimName/:claimId/', serveAsset); + app.get('/:identifier/:claim', serveByIdentifierAndClaim); + app.get('/:claim', serveByClaim); }; diff --git a/server/routes/pages/index.js b/server/routes/pages/index.js index 2c62b1aa..2dff606b 100644 --- a/server/routes/pages/index.js +++ b/server/routes/pages/index.js @@ -1,5 +1,5 @@ const handlePageRequest = require('../../controllers/pages/sendReactApp'); -const handleEmbedRequest = require('../../controllers/pages/sendEmbedPage'); +const handleVideoEmbedRequest = require('../../controllers/pages/sendVideoEmbedPage'); const redirect = require('../../controllers/utils/redirect'); module.exports = (app) => { @@ -10,5 +10,5 @@ module.exports = (app) => { app.get('/popular', handlePageRequest); app.get('/new', handlePageRequest); app.get('/multisite', handlePageRequest); - app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter) + app.get('/video-embed/:name/:claimId', handleVideoEmbedRequest); // for twitter }; diff --git a/test/test.html b/test/test.html new file mode 100644 index 00000000..01a5d622 --- /dev/null +++ b/test/test.html @@ -0,0 +1,21 @@ + + +
+ + + +no identifier, no ending
+ +no identifier, yes ending
+ +yes identifier, no ending
+ +yes identifier, yes ending
+ + +