001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.components.limiter.interceptor;
017
018
019import com.jfinal.aop.Interceptor;
020import com.jfinal.aop.Invocation;
021import io.jboot.components.limiter.LimitScope;
022import io.jboot.components.limiter.LimitType;
023import io.jboot.components.limiter.LimiterManager;
024import io.jboot.components.limiter.annotation.EnableLimit;
025import io.jboot.utils.AnnotationUtil;
026import io.jboot.utils.RequestUtil;
027import io.jboot.utils.StrUtil;
028
029public class LimiterInterceptor extends BaseLimiterInterceptor implements Interceptor {
030
031    @Override
032    public void intercept(Invocation inv) {
033        if (inv.isActionInvocation() && LimiterManager.me().isInIpWhitelist(RequestUtil.getIpAddress(inv.getController().getRequest()))) {
034            inv.invoke();
035        } else {
036            String packageOrTarget = getPackageOrTarget(inv);
037            EnableLimit enableLimit = inv.getMethod().getAnnotation(EnableLimit.class);
038            String resource = StrUtil.obtainDefault(enableLimit.resource(), packageOrTarget);
039            doInterceptByLimitInfo(enableLimit, resource, inv);
040        }
041    }
042
043
044    private void doInterceptByLimitInfo(EnableLimit enableLimit, String resource, Invocation inv) {
045        String type = AnnotationUtil.get(enableLimit.type());
046        switch (type) {
047            case LimitType.CONCURRENCY:
048                if (LimitScope.CLUSTER == enableLimit.scope()) {
049                    throw new IllegalArgumentException("Concurrency limit for cluster not implement!");
050                }
051                doInterceptForConcurrency(enableLimit.rate(), resource, enableLimit.fallback(), inv);
052                break;
053            case LimitType.IP_CONCURRENCY:
054                if (LimitScope.CLUSTER == enableLimit.scope()) {
055                    throw new IllegalArgumentException("Ip limit for cluster not implement!");
056                }
057                String resKey1 = RequestUtil.getIpAddress(inv.getController().getRequest()) + ":" + resource;
058                doInterceptForConcurrency(enableLimit.rate(), resKey1, enableLimit.fallback(), inv);
059                break;
060            case LimitType.TOKEN_BUCKET:
061                if (LimitScope.CLUSTER == enableLimit.scope()) {
062                    doInterceptForTokenBucketWithCluster(enableLimit.rate(), resource, enableLimit.fallback(), inv);
063                } else {
064                    doInterceptForTokenBucket(enableLimit.rate(), resource, enableLimit.fallback(), inv);
065                }
066                break;
067            case LimitType.IP_TOKEN_BUCKET:
068                String resKey2 = RequestUtil.getIpAddress(inv.getController().getRequest()) + ":" + resource;
069                if (LimitScope.CLUSTER == enableLimit.scope()) {
070                    doInterceptForTokenBucketWithCluster(enableLimit.rate(), resKey2, enableLimit.fallback(), inv);
071                } else {
072                    doInterceptForTokenBucket(enableLimit.rate(), resKey2, enableLimit.fallback(), inv);
073                }
074                break;
075        }
076    }
077
078
079}