updated routes to return proper error codes

This commit is contained in:
bill bittner 2018-02-13 12:19:57 -08:00
parent 5845a07a9d
commit aedc636241
10 changed files with 93 additions and 135 deletions

View file

@ -1,37 +1,30 @@
const logger = require('winston');
module.exports = {
returnErrorMessageAndStatus: function (error) {
let status, message;
// check for daemon being turned off
if (error.code === 'ECONNREFUSED') {
status = 200;
message = 'Connection refused. The daemon may not be running.';
// check for thrown errors
} else if (error.message) {
status = 200;
message = error.message;
// fallback for everything else
} else {
status = 400;
message = error;
}
return [status, message];
},
handleRequestError: function (originalUrl, ip, error, res) {
logger.error(`Request Error on ${originalUrl}`, module.exports.useObjectPropertiesIfNoKeys(error));
const [status, message] = module.exports.returnErrorMessageAndStatus(error);
res
.status(status)
.render('requestError', module.exports.createErrorResponsePayload(status, message));
},
handleApiError: function (originalUrl, ip, error, res) {
logger.error(`Api Error on ${originalUrl}`, module.exports.useObjectPropertiesIfNoKeys(error));
handleErrorResponse: function (originalUrl, ip, error, res) {
logger.error(`Error on ${originalUrl}`, module.exports.useObjectPropertiesIfNoKeys(error));
const [status, message] = module.exports.returnErrorMessageAndStatus(error);
res
.status(status)
.json(module.exports.createErrorResponsePayload(status, message));
},
returnErrorMessageAndStatus: function (error) {
let status, message;
// check for daemon being turned off
if (error.code === 'ECONNREFUSED') {
status = 503;
message = 'Connection refused. The daemon may not be running.';
// fallback for everything else
} else {
status = 400;
if (error.message) {
message = error.message;
} else {
message = error;
};
};
return [status, message];
},
useObjectPropertiesIfNoKeys: function (err) {
if (Object.keys(err).length === 0) {
let newErrorObject = {};

View file

@ -21,29 +21,21 @@ class NavBar extends React.Component {
checkForLoggedInUser () {
const params = {credentials: 'include'};
request('/user', params)
.then(({success, message, data}) => {
if (success) {
.then(({ data }) => {
this.props.onChannelLogin(data.channelName, data.shortChannelId, data.channelClaimId);
} else {
console.log(message);
}
})
.catch(error => {
console.log('request encountered an error', error);
console.log('/user error:', error.message);
});
}
logoutUser () {
const params = {credentials: 'include'};
request('/logout', params)
.then(({success, message}) => {
if (success) {
.then(() => {
this.props.onChannelLogout();
} else {
console.log(message);
}
})
.catch(error => {
console.log('request encountered an error', error);
console.log('/logout error', error.message);
});
}
handleSelection (event) {

View file

@ -8,28 +8,22 @@ function* retrieveFile (action) {
const name = action.data.name;
const claimId = action.data.claimId;
// see if the file is available
let success, message, isAvailable;
let isAvailable;
try {
({ success, message, data: isAvailable } = yield call(checkFileAvailability, name, claimId));
({ data: isAvailable } = yield call(checkFileAvailability, name, claimId));
} catch (error) {
return yield put(updateDisplayAssetError(error.message));
};
if (!success) {
return yield put(updateDisplayAssetError(message));
}
if (isAvailable) {
return yield put(updateFileAvailability(AVAILABLE));
}
yield put(updateFileAvailability(UNAVAILABLE));
// initiate get request for the file
try {
({ success, message } = yield call(triggerClaimGet, name, claimId));
yield call(triggerClaimGet, name, claimId);
} catch (error) {
return yield put(updateDisplayAssetError(error.message));
};
if (!success) {
return yield put(updateDisplayAssetError(message));
}
yield put(updateFileAvailability(AVAILABLE));
};

View file

@ -6,32 +6,28 @@ import { getChannelData } from 'api/channelApi';
function* newAssetRequest (action) {
const { id, name, modifier } = action.data;
let success, message, longId;
console.log('getting asset long id');
let longId;
try {
({success, message, data: longId} = yield call(getLongClaimId, name, modifier));
({data: longId} = yield call(getLongClaimId, name, modifier));
} catch (error) {
console.log('error:', error);
return yield put(updateRequestError(error.message));
}
if (!success) {
return yield put(updateRequestError(message));
}
yield put(addAssetRequest(id, null, name, longId));
yield put(showNewAsset(name, longId));
};
function* newChannelRequest (action) {
const { id, name, channelId } = action.data;
let success, message, data;
console.log('getting channel long id');
let data;
try {
({success, message, data} = yield call(getChannelData, name, channelId));
({data} = yield call(getChannelData, name, channelId));
} catch (error) {
// return yield put(addChannelRequest(id, error.message, null, null, null));
return yield put(updateRequestError(error.message));
}
if (!success) {
// return yield put(addChannelRequest(id, message, null, null, null));
return yield put(updateRequestError(message));
}
const { longChannelClaimId: longId, shortChannelClaimId: shortId } = data;
yield put(addChannelRequest(id, null, name, longId, shortId));
yield put(showNewChannel(name, shortId, longId));

View file

@ -7,27 +7,20 @@ function* getAssetDataAndShowAsset (action) {
const {id, name, claimId} = action.data;
// get short Id
console.log('getting short id');
let success, message, shortId;
let shortId;
try {
({success, message, data: shortId} = yield call(getShortId, name, claimId));
({data: shortId} = yield call(getShortId, name, claimId));
} catch (error) {
return yield put(updateRequestError(error.message));
}
if (!success) {
return yield put(updateRequestError(message));
}
// if no error, get claim data
console.log('getting claim data');
success = null;
let claimData;
try {
({success, message, data: claimData} = yield call(getClaimData, name, claimId));
({data: claimData} = yield call(getClaimData, name, claimId));
} catch (error) {
return yield put(updateRequestError(error.message));
}
if (!success) {
return yield put(updateRequestError(message));
}
yield put(addAssetToAssetList(id, null, name, claimId, shortId, claimData));
yield put(updateRequestError(null));
}

View file

@ -5,15 +5,12 @@ import { getChannelClaims } from 'api/channelApi';
function* getChannelClaimsAndShowChannel (action) {
const { id, name, shortId, longId } = action.data;
let success, message, claimsData;
let claimsData;
try {
({ success, message, data: claimsData } = yield call(getChannelClaims, name, longId, 1));
({ data: claimsData } = yield call(getChannelClaims, name, longId, 1));
} catch (error) {
return yield put(updateRequestError(error.message));
}
if (!success) {
return yield put(updateRequestError(message));
}
yield put(addNewChannelToChannelList(id, name, shortId, longId, claimsData));
yield put(updateRequestError(null));
}
@ -24,15 +21,12 @@ export function* watchShowNewChannel () {
function* getNewClaimsAndUpdateClaimsList (action) {
const { channelKey, name, longId, page } = action.data;
let success, message, claimsData;
let claimsData;
try {
({ success, message, data: claimsData } = yield call(getChannelClaims, name, longId, page));
({ data: claimsData } = yield call(getChannelClaims, name, longId, page));
} catch (error) {
return yield put(updateRequestError(error.message));
}
if (!success) {
return yield put(updateRequestError(message));
}
yield put(updateChannelClaims(channelKey, claimsData));
}

View file

@ -13,18 +13,18 @@ function parseJSON (response) {
}
/**
* Checks if a network request came back fine, and throws an error if not
* Parses the status returned by a network request
*
* @param {object} response A response from a network request
* @param {object} response The parsed JSON from the network request
*
* @return {object|undefined} Returns either the response, or throws an error
* @return {object | undefined} Returns object with status and statusText, or undefined
*/
function checkStatus (response) {
function checkStatus (response, jsonResponse) {
if (response.status >= 200 && response.status < 300) {
return response;
return jsonResponse;
}
const error = new Error(response.statusText);
const error = new Error(jsonResponse.message);
error.response = response;
throw error;
}
@ -37,8 +37,13 @@ function checkStatus (response) {
*
* @return {object} The response data
*/
export default function request (url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON);
.then(response => {
return Promise.all([response, parseJSON(response)]);
})
.then(([response, jsonResponse]) => {
return checkStatus(response, jsonResponse);
});
}

View file

@ -16,7 +16,7 @@ const NO_CLAIM = 'NO_CLAIM';
module.exports = (app) => {
// route to check whether site has published to a channel
app.get('/api/channel/availability/:name', ({ params }, res) => {
app.get('/api/channel/availability/:name', ({ ip, originalUrl, params }, res) => {
checkChannelAvailability(params.name)
.then(result => {
if (result === true) {
@ -26,35 +26,32 @@ module.exports = (app) => {
}
})
.catch(error => {
res.status(500).json(error);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to get a short channel id from long channel Id
app.get('/api/channel/short-id/:longId/:name', ({ ip, originalUrl, params }, res) => {
db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)
.then(shortId => {
logger.debug('sending back short channel id', shortId);
res.status(200).json(shortId);
})
.catch(error => {
logger.error('api error getting short channel id', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
app.get('/api/channel/data/:channelName/:channelClaimId', ({ ip, originalUrl, body, params }, res) => {
const channelName = params.channelName;
let channelClaimId = params.channelClaimId;
if (channelClaimId === 'none') channelClaimId = null;
getChannelData(channelName, channelClaimId, 0) // getChannelViewData(channelName, channelId, 0)
getChannelData(channelName, channelClaimId, 0)
.then(data => {
if (data === NO_CHANNEL) {
return res.status(200).json({success: false, message: 'No matching channel was found'});
return res.status(404).json({success: false, message: 'No matching channel was found'});
}
res.status(200).json({success: true, data});
})
.catch(error => {
logger.error('api error getting channel contents', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
app.get('/api/channel/claims/:channelName/:channelClaimId/:page', ({ ip, originalUrl, body, params }, res) => {
@ -62,16 +59,15 @@ module.exports = (app) => {
let channelClaimId = params.channelClaimId;
if (channelClaimId === 'none') channelClaimId = null;
const page = params.page;
getChannelClaims(channelName, channelClaimId, page)// getChannelViewData(channelName, channelClaimId, page)
getChannelClaims(channelName, channelClaimId, page)
.then(data => {
if (data === NO_CHANNEL) {
return res.status(200).json({success: false, message: 'No matching channel was found'});
return res.status(404).json({success: false, message: 'No matching channel was found'});
}
res.status(200).json({success: true, data});
})
.catch(error => {
logger.error('api error getting channel contents', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to run a claim_list request on the daemon
@ -81,7 +77,7 @@ module.exports = (app) => {
res.status(200).json(claimsList);
})
.catch(error => {
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to get an asset
@ -107,11 +103,11 @@ module.exports = (app) => {
res.status(200).json({ success: true, message, completed });
})
.catch(error => {
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to check whether this site published to a claim
app.get('/api/claim/availability/:name', ({ params }, res) => {
app.get('/api/claim/availability/:name', ({ ip, originalUrl, params }, res) => {
checkClaimNameAvailability(params.name)
.then(result => {
if (result === true) {
@ -121,7 +117,7 @@ module.exports = (app) => {
}
})
.catch(error => {
res.status(500).json(error);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to run a resolve request on the daemon
@ -131,7 +127,7 @@ module.exports = (app) => {
res.status(200).json(resolvedUri);
})
.catch(error => {
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to run a publish request on the daemon
@ -151,7 +147,6 @@ module.exports = (app) => {
({fileName, filePath, fileType} = parsePublishApiRequestFiles(files));
({channelName, channelPassword} = parsePublishApiChannel(body, user));
} catch (error) {
logger.debug('publish request rejected, insufficient request parameters', error);
return res.status(400).json({success: false, message: error.message});
}
// check channel authorization
@ -193,18 +188,17 @@ module.exports = (app) => {
sendGoogleAnalyticsTiming(timingActionType, headers, ip, originalUrl, publishStartTime, publishEndTime);
})
.catch(error => {
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to get a short claim id from long claim Id
app.get('/api/claim/short-id/:longId/:name', ({ params }, res) => {
app.get('/api/claim/short-id/:longId/:name', ({ ip, originalUrl, body, params }, res) => {
db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)
.then(shortId => {
res.status(200).json({success: true, data: shortId});
})
.catch(error => {
logger.error('api error getting short channel id', error);
res.status(200).json({success: false, message: error.message});
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
app.post('/api/claim/long-id', ({ ip, originalUrl, body, params }, res) => {
@ -216,16 +210,15 @@ module.exports = (app) => {
getClaimId(channelName, channelClaimId, claimName, claimId)
.then(result => {
if (result === NO_CHANNEL) {
return res.status(200).json({success: false, message: 'No matching channel could be found'});
return res.status(404).json({success: false, message: 'No matching channel could be found'});
}
if (result === NO_CLAIM) {
return res.status(200).json({success: false, message: 'No matching claim id could be found'});
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 => {
logger.error('api error getting long claim id', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
app.get('/api/claim/data/:claimName/:claimId', ({ ip, originalUrl, body, params }, res) => {
@ -235,29 +228,27 @@ module.exports = (app) => {
db.Claim.resolveClaim(claimName, claimId)
.then(claimInfo => {
if (!claimInfo) {
return res.status(200).json({success: false, message: 'No claim could be found'});
return res.status(404).json({success: false, message: 'No claim could be found'});
}
res.status(200).json({success: true, data: claimInfo});
})
.catch(error => {
logger.error('api error getting long claim id', error);
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
// route to see if asset is available locally
app.get('/api/file/availability/:name/:claimId', ({ ip, originalUrl, params }, res) => {
const name = params.name;
const claimId = params.claimId;
let isAvailable = false;
db.File.findOne({where: {name, claimId}})
.then(result => {
if (result) {
isAvailable = true;
return res.status(200).json({success: true, data: true});
}
res.status(200).json({success: true, data: isAvailable});
res.status(200).json({success: true, data: false});
})
.catch(error => {
errorHandlers.handleApiError(originalUrl, ip, error, res);
errorHandlers.handleErrorResponse(originalUrl, ip, error, res);
});
});
};

View file

@ -20,7 +20,7 @@ module.exports = (app) => {
return next(err);
}
if (!user) {
return res.status(200).json({
return res.status(400).json({
success: false,
message: info.message,
});
@ -49,7 +49,7 @@ module.exports = (app) => {
if (req.user) {
res.status(200).json({success: true, data: req.user});
} else {
res.status(200).json({success: false, message: 'user is not logged in'});
res.status(401).json({success: false, message: 'user is not logged in'});
}
});
};

View file

@ -1,7 +1,7 @@
const logger = require('winston');
const { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');
const serveHelpers = require('../helpers/serveHelpers.js');
const { handleRequestError } = require('../helpers/errorHandlers.js');
const { handleErrorResponse } = require('../helpers/errorHandlers.js');
const lbryUri = require('../helpers/lbryUri.js');
const SERVE = 'SERVE';
@ -92,7 +92,7 @@ module.exports = (app) => {
try {
({ hasFileExtension } = lbryUri.parseModifier(params.claim));
} catch (error) {
return res.status(200).json({success: false, message: error.message});
return res.status(400).json({success: false, message: error.message});
}
let responseType = determineResponseType(hasFileExtension, headers);
if (responseType !== SERVE) {
@ -103,14 +103,14 @@ module.exports = (app) => {
try {
({ claimName } = lbryUri.parseClaim(params.claim));
} catch (error) {
return res.status(200).json({success: false, message: error.message});
return res.status(400).json({success: false, message: error.message});
}
// parse the identifier
let isChannel, channelName, channelClaimId, claimId;
try {
({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(params.identifier));
} catch (error) {
return handleRequestError(originalUrl, ip, error, res);
return res.status(400).json({success: false, message: error.message});
}
if (!isChannel) {
[claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);
@ -121,15 +121,15 @@ module.exports = (app) => {
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'});
return res.status(404).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'});
return res.status(404).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);
handleErrorResponse(originalUrl, ip, error, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
});
});
@ -140,7 +140,7 @@ module.exports = (app) => {
try {
({ hasFileExtension } = lbryUri.parseModifier(params.claim));
} catch (error) {
return res.status(200).json({success: false, message: error.message});
return res.status(400).json({success: false, message: error.message});
}
let responseType = determineResponseType(hasFileExtension, headers);
if (responseType !== SERVE) {
@ -151,7 +151,7 @@ module.exports = (app) => {
try {
({claimName} = lbryUri.parseClaim(params.claim));
} catch (error) {
return res.status(200).json({success: false, message: error.message});
return res.status(400).json({success: false, message: error.message});
}
// log the request data for debugging
logRequestData(responseType, claimName, null, null);
@ -159,13 +159,13 @@ module.exports = (app) => {
getClaimId(null, null, claimName, null)
.then(fullClaimId => {
if (fullClaimId === NO_CLAIM) {
return res.status(200).render('index');
return res.status(404).json({success: false, message: 'no claim id could be found'});
}
serveAssetToClient(fullClaimId, claimName, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
})
.catch(error => {
handleRequestError(originalUrl, ip, error, res);
handleErrorResponse(originalUrl, ip, error, res);
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
});
});