Authored by 陈峰

Merge branch 'release/6.5.2' into 'master'

Release/6.5.2



See merge request !235
... ... @@ -150,5 +150,4 @@ library
### foreman ###
Procfile
.env
yarn.lock
package-json.lock
... ...
... ... @@ -26,9 +26,12 @@ const isHuman = (req, res) => {
remoteIp = arr[0];
}
const apiLimitValidate = req.session.apiLimitValidate;
logger.info('isHuman', remoteIp);
robotCheckService.removeBlack(remoteIp).then(() => {
delete req.session.apiLimitValidate;
logger.warn('isHuman', remoteIp);
return robotCheckService.removeBlack(remoteIp, apiLimitValidate).then(() => {
return res.json({
code: 200
});
... ...
... ... @@ -5,6 +5,7 @@ const Promise = require('bluebird');
const co = Promise.coroutine;
const config = global.yoho.config;
const _ = require('lodash');
const humanExpire = 3600;
const HeaderModel = require('../../../doraemon/models/header');
... ... @@ -16,8 +17,17 @@ const index = co(function* (channel) {
};
});
const removeBlack = (remoteIp) => {
let operations = [cache.delAsync(`${config.app}:limiter:${remoteIp}`)];
const removeBlack = (remoteIp, apiLimitValidate) => {
let operations = [];
operations.push(cache.delAsync(`${config.app}:limiter:${remoteIp}`));
// 验证码之后一小时之内不再限制qps
if (apiLimitValidate) {
operations.push(cache.setAsync(`${config.app}:limiter:api:ishuman:${remoteIp}`, 1, humanExpire));
} else {
operations.push(cache.setAsync(`${config.app}:limiter:ishuman:${remoteIp}`, 1, humanExpire));
}
_.forEach(config.REQUEST_LIMIT, (val, key) => {
operations.push(cache.delAsync(`${config.app}:limiter:${key}:max:${remoteIp}`));
... ...
... ... @@ -4,6 +4,13 @@
<div class="captcha-wrap"> </div>
<a class="btn confirm">确定</a>
</div>
<div class="download">
<div class="bottom-down">
<div class="qr-code right"></div>
<a href="http://itunes.apple.com/us/app/id490655927?ls=1&amp;mt=8" target="_blank" class="down-app-btn down-btns"></a>
<a href="http://yoho-apps.qiniudn.com/YohoBuy_YOHO.apk" target="_blank" class="down-apk-btn down-btns"></a>
</div>
</div>
</div>
{{> gee-captcha}}
... ...
... ... @@ -175,15 +175,15 @@ module.exports = {
},
REQUEST_LIMIT: {
// 10s 最多访问5次
10: 10,
10: 5,
// 30s 最多访问15次
30: 20,
// 30s 最多访问10次
30: 10,
// 60s 最多访问15次
60: 30,
60: 15,
// 100s 最多访问15
// 100s 最多访问100
600: 100
}
};
... ...
... ... @@ -4,11 +4,14 @@
*/
const headerModel = require('../models/header');
const logger = global.yoho.logger;
const cache = global.yoho.cache.master;
const helpers = global.yoho.helpers;
const sender = global.yoho.apmSender;
const config = global.yoho.config;
const hostname = require('os').hostname();
const routeEncode = require('./route-encode');
const _ = require('lodash');
const limiterIpTime = 3600;
const forceNoCache = (res) => {
if (res) {
... ... @@ -48,13 +51,20 @@ exports.notFound = () => {
* @return {[type]}
*/
exports.serverError = () => {
return (err, req, res, next) => {
return async (err, req, res, next) => {
forceNoCache(res);
const uid = req.user ? req.user.uid : 0;
const udid = _.get(req, 'cookies.udid', 'yoho');
let errorCode = 500;
if (req.isApmReport) {
err = err || {
code: 500
};
err.code = err.code || err.statusCode || 500;
if (req.isApmReport && !err.apiError) { // apierror在node lib中已经上报过了 不需要再次上报
// 上报服务端错误
sender.addMessage({
measurement: 'error-report',
... ... @@ -79,7 +89,7 @@ exports.serverError = () => {
logger.error(`error at path: ${req.url}`);
logger.error(err);
if (err && err.code === 401) {
if (err.code === 401) {
if (req.xhr) {
err.data = {refer: helpers.urlFormat('/signin.html', {refer: req.get('Referer') || ''})};
return res.json(err);
... ... @@ -87,11 +97,41 @@ exports.serverError = () => {
return res.redirect(helpers.urlFormat('/signin.html', {refer: req.fullUrl()}));
}
}
if (err.code === 9999991 || err.code === 9999992) {
let remoteIp = req.yoho.clientIp;
const isHuman = await cache.getAsync(`${config.app}:limiter:api:ishuman:${remoteIp}`);
if (!isHuman) {
if (remoteIp.indexOf(',') > 0) {
let arr = remoteIp.split(',');
remoteIp = arr[0];
}
cache.setAsync(`${config.app}:limiter:${remoteIp}`, 1, limiterIpTime);
let limitAPI = helpers.urlFormat('/3party/check', {refer: req.get('Referer') || ''});
let limitPage = helpers.urlFormat('/3party/check', {
refer: req.protocol + '://' + req.get('host') + req.originalUrl
});
req.session.apiLimitValidate = true;
if (req.xhr) {
return res.status(510).json({
code: err.code,
data: {refer: limitAPI}
});
}
return res.redirect(limitPage);
}
errorCode = 510;
}
if (!res.headersSent) {
if (req.xhr) {
return res.status(500).json({
code: 500,
return res.status(errorCode).json({
code: errorCode,
message: '服务器错误!'
});
}
... ... @@ -99,7 +139,7 @@ exports.serverError = () => {
const renderErrPage = (result) => {
result = result || {};
res.status(500).render('error/500', {
res.status(errorCode).render(`error/${errorCode}`, {
module: 'common',
page: 'error',
err: err,
... ...
... ... @@ -24,8 +24,7 @@ module.exports = (req, res, next) => {
}
if (req.xhr) {
return res.json({
code: 400,
return res.status(510).json({
data: {refer: limitAPI}
});
}
... ...
... ... @@ -27,12 +27,18 @@ module.exports = (limiter, policy) => {
getOp[key] = cache.getAsync(ruleKeys[key]);
});
getOp.human = cache.getAsync(`${config.app}:limiter:ishuman:${limiter.remoteIp}`);
return Promise.props(getOp).then((results) => {
logger.debug(MAX_TIMES);
logger.debug(_.values(ruleKeys));
logger.debug(results);
if (results.human) { // 经过验证码之后1小时有效期内不再验证qps
return Promise.resolve(true);
}
// 遍历限制规则,若满足返回相应处理策略, 否则页面访问次数加1
let operation = [];
... ... @@ -42,6 +48,7 @@ module.exports = (limiter, policy) => {
if (!results[key]) {
operation.push(cache.setAsync(cacheKey, 1, +key));
} else if (+results[key] > +val) {
logger.warn(`${config.app}:limiter:${limiter.remoteIp}`);
// ip限制1小时
operation.push(cache.setAsync(`${config.app}:limiter:${limiter.remoteIp}`, 1, limiterIpTime));
... ...
<div class="wrapper screen">
<div class="clear wrapper-404">
<div class="left"><img src="http://static.yohobuy.com/images/v3/index/404.png"></div>
<div class="right right-tips">
<p class="text1">服务器繁忙请重试!</p>
<p class="text2">
</p>
<p class="text3"><a href="http://www.yohobuy.com/product/new" class="button">浏览新品</a>&nbsp;&nbsp;<a href="http://www.yohobuy.com/" class="button">返回首页</a></p>
</div>
</div>
</div>
\ No newline at end of file
... ...
{
"name": "yohobuy-node",
"version": "6.1.28",
"version": "6.1.29",
"private": true,
"description": "A New Yohobuy Project With Express",
"repository": {
... ... @@ -57,7 +57,7 @@
"urlencode": "^1.1.0",
"uuid": "^2.0.2",
"yoho-express-session": "^2.0.0",
"yoho-node-lib": "=0.6.1",
"yoho-node-lib": "=0.6.3",
"yoho-zookeeper": "^1.0.8"
},
"devDependencies": {
... ...
... ... @@ -66,7 +66,8 @@ const getEntries = () => {
'yoho-slider',
'yoho-jquery-pjax',
'yoho-jquery-dotdotdot',
'regenerator-runtime/runtime'
'regenerator-runtime/runtime',
path.join(__dirname, '../js/global.js')
],
base: path.join(__dirname, '../scss/base.css')
};
... ...
const $ = require('yoho-jquery');
// 注册ajaxError处理服务端异常
$(document).ajaxError((event, xhr) => {
if (xhr.responseJSON) {
if (xhr.status === 510 && xhr.responseJSON.data && xhr.responseJSON.data.refer) {
window.location.href = xhr.responseJSON.data.refer;
}
}
});
... ...
.robot-check-page {
height: 400px;
.captcha {
width: 1150px;
margin-left: auto;
margin-right: auto;
margin-top: 150px;
margin-top: 100px;
}
.download {
margin-bottom: 100px;
}
.title {
... ... @@ -34,4 +36,32 @@
cursor: pointer;
letter-spacing: 10px;
}
.bottom-down {
width: 350px;
margin: 0 auto;
overflow: hidden;
padding-top: 34px;
.qr-code {
width: 130px;
height: 130px;
background: url("/download/down-qr-code.png");
}
.down-btns {
width: 200px;
height: 60px;
display: block;
}
.down-app-btn {
margin-bottom: 8px;
background: url("/download/app-down.png");
}
.down-apk-btn {
background: url("/download/apk-down.png");
}
}
}
... ...
This diff could not be displayed because it is too large.