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.gateway;
017
018import com.alibaba.csp.sentinel.*;
019import com.alibaba.csp.sentinel.slots.block.BlockException;
020import com.alibaba.csp.sentinel.util.StringUtil;
021import com.jfinal.kit.LogKit;
022import io.jboot.support.sentinel.SentinelUtil;
023import io.jboot.utils.StrUtil;
024
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027import java.io.IOException;
028
029public class GatewaySentinelProcesser {
030
031
032    public void process(GatewayHttpProxy proxy, String proxyUrl, JbootGatewayConfig config, HttpServletRequest req, HttpServletResponse resp, boolean skipExceptionRender) {
033        Entry entry = null;
034        String resourceName = SentinelUtil.buildResource(req);
035        try {
036            entry = SphU.entry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, EntryType.IN);
037            proxy.sendRequest(proxyUrl, req, resp);
038        } catch (BlockException ex) {
039            if (skipExceptionRender) {
040                GatewayErrorRender errorRender = JbootGatewayManager.me().getGatewayErrorRender();
041                if (errorRender != null) {
042                    errorRender.renderError(ex, GatewayErrorRender.sentinelBlockedError, config, req, resp);
043                } else {
044                    processBlocked(config, req, resp);
045                }
046            } else {
047                proxy.setException(ex);
048            }
049        } finally {
050            if (proxy.getException() != null) {
051                Tracer.traceEntry(proxy.getException(), entry);
052            }
053            if (entry != null) {
054                entry.exit();
055            }
056        }
057    }
058
059
060    private void processBlocked(JbootGatewayConfig config, HttpServletRequest req, HttpServletResponse resp) {
061        StringBuffer url = req.getRequestURL();
062
063        if ("GET".equalsIgnoreCase(req.getMethod()) && StrUtil.isNotBlank(req.getQueryString())) {
064            url.append("?").append(req.getQueryString());
065        }
066
067        try {
068            if (StringUtil.isNotBlank(config.getSentinelBlockPage())) {
069                String redirectUrl = config.getSentinelBlockPage() + "?http_referer=" + url.toString();
070                resp.sendRedirect(redirectUrl);
071            } else if (config.getSentinelBlockJsonMap() != null && !config.getSentinelBlockJsonMap().isEmpty()) {
072                SentinelUtil.writeDefaultBlockedJson(resp, config.getSentinelBlockJsonMap());
073            } else {
074                SentinelUtil.writeDefaultBlockedPage(resp);
075            }
076        } catch (IOException ex) {
077            LogKit.error(ex.toString(), ex);
078        }
079    }
080
081
082}