added regex url parsing
This commit is contained in:
parent
4f8cdc06b0
commit
87d026b5ec
1 changed files with 124 additions and 61 deletions
|
@ -7,7 +7,6 @@ const db = require('../models');
|
|||
const SERVE = 'SERVE';
|
||||
const SHOW = 'SHOW';
|
||||
const SHOWLITE = 'SHOWLITE';
|
||||
const CLAIM_ID_CHAR = ':';
|
||||
const CHANNEL_CHAR = '@';
|
||||
const CLAIMS_PER_PAGE = 10;
|
||||
const NO_CHANNEL = 'NO_CHANNEL';
|
||||
|
@ -26,24 +25,6 @@ function isValidShortIdOrClaimId (input) {
|
|||
return (isValidClaimId(input) || isValidShortId(input));
|
||||
}
|
||||
|
||||
function isUriAChannel (name) {
|
||||
return (name.charAt(0) === CHANNEL_CHAR);
|
||||
}
|
||||
|
||||
function returnChannelNameFromUri (uri) {
|
||||
if (uri.indexOf(CLAIM_ID_CHAR) !== -1) {
|
||||
return uri.substring(0, uri.indexOf(CLAIM_ID_CHAR));
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
function returnChannelIdFromUri (uri) {
|
||||
if (uri.indexOf(CLAIM_ID_CHAR) !== -1) {
|
||||
return uri.substring(uri.indexOf(CLAIM_ID_CHAR) + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPage (query) {
|
||||
if (query.p) {
|
||||
return parseInt(query.p);
|
||||
|
@ -128,11 +109,7 @@ function sendChannelInfoAndContentToClient (result, query, res) {
|
|||
}
|
||||
}
|
||||
|
||||
function showChannelPageToClient (uri, originalUrl, ip, query, res) {
|
||||
let channelName = returnChannelNameFromUri(uri);
|
||||
logger.debug('channel name =', channelName);
|
||||
let channelClaimId = returnChannelIdFromUri(uri);
|
||||
logger.debug('channel Id =', channelClaimId);
|
||||
function showChannelPageToClient (channelName, channelClaimId, originalUrl, ip, query, res) {
|
||||
// 1. retrieve the channel contents
|
||||
getChannelInfoAndContent(channelName, channelClaimId)
|
||||
.then(result => {
|
||||
|
@ -143,17 +120,13 @@ function showChannelPageToClient (uri, originalUrl, ip, query, res) {
|
|||
});
|
||||
}
|
||||
|
||||
function characterExistsInString (character, string) {
|
||||
return (string.indexOf(character) !== -1);
|
||||
}
|
||||
|
||||
function clientAcceptsHtml (headers) {
|
||||
return headers['accept'] && headers['accept'].split(',').includes('text/html');
|
||||
}
|
||||
|
||||
function determineResponseType (uri, headers) {
|
||||
function determineResponseType (isServeRequest, headers) {
|
||||
let responseType;
|
||||
if (characterExistsInString('.', uri)) {
|
||||
if (isServeRequest) {
|
||||
responseType = SERVE;
|
||||
if (clientAcceptsHtml(headers)) { // this is in case a serve request comes from a browser
|
||||
responseType = SHOWLITE;
|
||||
|
@ -167,18 +140,6 @@ function determineResponseType (uri, headers) {
|
|||
return responseType;
|
||||
}
|
||||
|
||||
function determineName (uri) {
|
||||
/* patch because twitter player preview adds '>' before file extension. */
|
||||
if (characterExistsInString('>', uri)) {
|
||||
return uri.substring(0, uri.indexOf('>'));
|
||||
}
|
||||
/* end patch */
|
||||
if (characterExistsInString('.', uri)) {
|
||||
return uri.substring(0, uri.indexOf('.'));
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
function showAssetToClient (claimId, name, res) {
|
||||
return Promise
|
||||
.all([db.Claim.resolveClaim(name, claimId), db.Claim.getShortClaimIdFromLongClaimId(claimId, name)])
|
||||
|
@ -250,23 +211,110 @@ function logRequestData (responseType, claimName, channelName, claimId) {
|
|||
logger.debug('claim id ===', claimId);
|
||||
}
|
||||
|
||||
const lbryuri = {};
|
||||
|
||||
lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g;
|
||||
lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||
|
||||
lbryuri.parseIdentifier = function (identifier) {
|
||||
logger.debug('parsing identifier:', identifier);
|
||||
const componentsRegex = new RegExp(
|
||||
'([^:$#/]*)' + // value (stops at the first separator or end)
|
||||
'([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
|
||||
);
|
||||
const [proto, value, modifierSeperator, modifier] = componentsRegex
|
||||
.exec(identifier)
|
||||
.map(match => match || null);
|
||||
logger.debug(`${proto}, ${value}, ${modifierSeperator}, ${modifier}`);
|
||||
|
||||
// Validate and process name
|
||||
const isChannel = value.startsWith(CHANNEL_CHAR);
|
||||
const channelName = isChannel ? value : null;
|
||||
let claimId;
|
||||
if (isChannel) {
|
||||
if (!channelName) {
|
||||
throw new Error('No channel name after @.');
|
||||
}
|
||||
const nameBadChars = (channelName).match(lbryuri.REGEXP_INVALID_URI);
|
||||
if (nameBadChars) {
|
||||
throw new Error(`Invalid characters in channel name: ${nameBadChars.join(', ')}.`);
|
||||
}
|
||||
} else {
|
||||
claimId = value;
|
||||
}
|
||||
|
||||
// Validate and process modifier
|
||||
let channelClaimId;
|
||||
if (modifierSeperator) {
|
||||
if (!modifier) {
|
||||
throw new Error(`No modifier provided after separator ${modifierSeperator}.`);
|
||||
}
|
||||
|
||||
if (modifierSeperator === ':') {
|
||||
channelClaimId = modifier;
|
||||
} else {
|
||||
throw new Error(`The ${modifierSeperator} modifier is not currently supported.`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
isChannel,
|
||||
channelName,
|
||||
channelClaimId,
|
||||
claimId,
|
||||
};
|
||||
};
|
||||
|
||||
lbryuri.parseName = function (name) {
|
||||
logger.debug('parsing name:', name);
|
||||
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)
|
||||
.map(match => match || null);
|
||||
logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);
|
||||
|
||||
// Validate and process name
|
||||
if (!claimName) {
|
||||
throw new Error('No claim name provided before .');
|
||||
}
|
||||
const nameBadChars = (claimName).match(lbryuri.REGEXP_INVALID_URI);
|
||||
if (nameBadChars) {
|
||||
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}.`);
|
||||
}
|
||||
if (modifierSeperator !== '.') {
|
||||
throw new Error(`The ${modifierSeperator} modifier is not supported in the claim name`);
|
||||
}
|
||||
isServeRequest = true;
|
||||
}
|
||||
return {
|
||||
claimName,
|
||||
isServeRequest,
|
||||
};
|
||||
};
|
||||
|
||||
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 identifier = params.identifier; // '@channel', '@channel:channelClaimId', or 'claimId'
|
||||
let name = params.name; // 'example' or 'example.ext'
|
||||
[identifier, name] = flipClaimNameAndIdForBackwardsCompatibility(identifier, name);
|
||||
let channelName = null;
|
||||
let claimId = null;
|
||||
let channelClaimId = null;
|
||||
let responseType = determineResponseType(name, headers);
|
||||
let claimName = determineName(name);
|
||||
if (isUriAChannel(identifier)) {
|
||||
channelName = returnChannelNameFromUri(identifier);
|
||||
channelClaimId = returnChannelIdFromUri(identifier);
|
||||
} else {
|
||||
claimId = identifier;
|
||||
let isChannel, channelName, channelClaimId, claimId, claimName, isServeRequest;
|
||||
try {
|
||||
({ isChannel, channelName, channelClaimId, claimId } = lbryuri.parseIdentifier(params.identifier));
|
||||
({ claimName, isServeRequest } = lbryuri.parseName(params.name));
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return res.status(400).json({success: false, message: error});
|
||||
}
|
||||
if (!isChannel) {
|
||||
[claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);
|
||||
}
|
||||
let responseType = determineResponseType(isServeRequest, headers);
|
||||
// log the request data for debugging
|
||||
logRequestData(responseType, claimName, channelName, claimId);
|
||||
// get the claim Id and then serve/show the asset
|
||||
|
@ -284,13 +332,28 @@ module.exports = (app) => {
|
|||
});
|
||||
});
|
||||
// route to serve the winning asset at a claim or a channel page
|
||||
app.get('/:uri', ({ headers, ip, originalUrl, params, query }, res) => {
|
||||
let uri = params.uri;
|
||||
if (isUriAChannel(uri)) {
|
||||
showChannelPageToClient(uri, originalUrl, ip, query, res);
|
||||
app.get('/:identifier', ({ headers, ip, originalUrl, params, query }, res) => {
|
||||
let isChannel, channelName, channelClaimId;
|
||||
try {
|
||||
({ isChannel, channelName, channelClaimId } = lbryuri.parseIdentifier(params.identifier));
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return res.status(400).json({success: false, message: error});
|
||||
}
|
||||
if (isChannel) {
|
||||
// log the request data for debugging
|
||||
logRequestData(null, null, channelName, null);
|
||||
// handle showing the channel page
|
||||
showChannelPageToClient(channelName, channelClaimId, originalUrl, ip, query, res);
|
||||
} else {
|
||||
let responseType = determineResponseType(uri, headers);
|
||||
let claimName = determineName(uri);
|
||||
let claimName, isServeRequest;
|
||||
try {
|
||||
({claimName, isServeRequest} = lbryuri.parseName(params.identifier));
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
return res.status(400).json({success: false, message: error});
|
||||
}
|
||||
let responseType = determineResponseType(isServeRequest, headers);
|
||||
// log the request data for debugging
|
||||
logRequestData(responseType, claimName, null, null);
|
||||
// get the claim Id and then serve/show the asset
|
||||
|
|
Loading…
Reference in a new issue