net.ymate.module.webproxy.WebProxy.java Source code

Java tutorial

Introduction

Here is the source code for net.ymate.module.webproxy.WebProxy.java

Source

/*
 * Copyright 2007-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.ymate.module.webproxy;

import net.ymate.framework.commons.ParamUtils;
import net.ymate.module.webproxy.impl.DefaultModuleCfg;
import net.ymate.platform.core.Version;
import net.ymate.platform.core.YMP;
import net.ymate.platform.core.module.IModule;
import net.ymate.platform.core.module.annotation.Module;
import net.ymate.platform.core.util.RuntimeUtils;
import net.ymate.platform.webmvc.WebMVC;
import net.ymate.platform.webmvc.base.Type;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * @author  (suninformation@163.com) on 17/3/29 ?3:21
 * @version 1.0
 */
@Module
public class WebProxy implements IModule, IWebProxy {

    private static final Log _LOG = LogFactory.getLog(WebProxy.class);

    public static final Version VERSION = new Version(1, 0, 0,
            WebProxy.class.getPackage().getImplementationVersion(), Version.VersionType.Alphal);

    private static volatile IWebProxy __instance;

    private YMP __owner;

    private IWebProxyModuleCfg __moduleCfg;

    private boolean __inited;

    public static IWebProxy get() {
        if (__instance == null) {
            synchronized (VERSION) {
                if (__instance == null) {
                    __instance = YMP.get().getModule(WebProxy.class);
                }
            }
        }
        return __instance;
    }

    public String getName() {
        return IWebProxy.MODULE_NAME;
    }

    public void init(YMP owner) throws Exception {
        if (!__inited) {
            //
            _LOG.info("Initializing ymate-module-webproxy-" + VERSION);
            //
            __owner = owner;
            __moduleCfg = new DefaultModuleCfg(owner);
            __owner.getEvents().registerEvent(WebProxyEvent.class);
            //
            _LOG.info("-->          service_base_url: " + __moduleCfg.getServiceBaseUrl());
            _LOG.info("-->            request_prefix: "
                    + StringUtils.defaultIfBlank(__moduleCfg.getServiceRequestPrefix(), "none"));
            _LOG.info("-->                     proxy: "
                    + (__moduleCfg.getProxy() != null ? __moduleCfg.getProxy().toString() : "none"));
            _LOG.info("-->   transfer_header_enabled: " + __moduleCfg.isTransferHeaderEnabled());
            if (__moduleCfg.isTransferHeaderEnabled()) {
                _LOG.info("--> transfer_header_whitelist: " + __moduleCfg.getTransferHeaderWhiteList());
                _LOG.info("--> transfer_header_blacklist: " + __moduleCfg.getTransferHeaderBlackList());
                _LOG.info("--> response_header_whitelist: " + __moduleCfg.getResponseHeaderWhileList());
            }
            _LOG.info("-->                use_caches: " + __moduleCfg.isUseCaches());
            _LOG.info("--> instance_follow_redirects: " + __moduleCfg.isInstanceFollowRedirects());
            _LOG.info("-->        connection_timeout: " + __moduleCfg.getConnectTimeout());
            _LOG.info("-->              read_timeout: " + __moduleCfg.getReadTimeout());
            //
            __inited = true;
        }
    }

    public boolean isInited() {
        return __inited;
    }

    private String __doParseContentBody(HttpURLConnection _conn, byte[] _content, String charset) throws Exception {
        if (StringUtils.contains(_conn.getHeaderField("Content-Encoding"), "gzip")) {
            ByteArrayInputStream _input = null;
            GZIPInputStream _gzip = null;
            ByteArrayOutputStream _output = null;
            try {
                _input = new ByteArrayInputStream(_content);
                _gzip = new GZIPInputStream(_input);
                _output = new ByteArrayOutputStream();
                //
                IOUtils.copyLarge(_gzip, _output);
                return new String(_output.toByteArray(), charset);
            } finally {
                IOUtils.closeQuietly(_output);
                IOUtils.closeQuietly(_gzip);
                IOUtils.closeQuietly(_input);
            }
        }
        return new String(_content, charset);
    }

    @SuppressWarnings("unchecked")
    public void transmission(HttpServletRequest request, HttpServletResponse response, String url,
            Type.HttpMethod method) throws Exception {
        StopWatch _consumeTime = null;
        long _threadId = 0;
        if (_LOG.isDebugEnabled()) {
            _consumeTime = new StopWatch();
            _consumeTime.start();
            _threadId = Thread.currentThread().getId();
            _LOG.debug("-------------------------------------------------");
            _LOG.debug("--> [" + _threadId + "] URL: " + url);
        }
        //
        HttpURLConnection _conn = null;
        try {
            if (__moduleCfg.isUseProxy()) {
                _conn = (HttpURLConnection) new URL(url).openConnection(__moduleCfg.getProxy());
            } else {
                _conn = (HttpURLConnection) new URL(url).openConnection();
            }
            _conn.setUseCaches(__moduleCfg.isUseCaches());
            _conn.setInstanceFollowRedirects(__moduleCfg.isInstanceFollowRedirects());
            //
            boolean _postFlag = Type.HttpMethod.POST.equals(method);
            boolean _multipartFlag = _postFlag && StringUtils.contains(request.getContentType(), "multipart/");
            if (_postFlag) {
                _conn.setDoOutput(true);
                _conn.setDoInput(true);
                _conn.setRequestMethod(method.name());
            }
            if (__moduleCfg.getConnectTimeout() > 0) {
                _conn.setConnectTimeout(__moduleCfg.getConnectTimeout());
            }
            if (__moduleCfg.getReadTimeout() > 0) {
                _conn.setReadTimeout(__moduleCfg.getReadTimeout());
            }
            //
            if (_LOG.isDebugEnabled()) {
                _LOG.debug("--> [" + _threadId + "] Method: " + method.name());
                _LOG.debug("--> [" + _threadId + "] Request Headers: ");
            }
            //
            Enumeration _header = request.getHeaderNames();
            while (_header.hasMoreElements()) {
                String _name = (String) _header.nextElement();
                String _value = request.getHeader(_name);
                boolean _flag = false;
                if (_postFlag && StringUtils.equalsIgnoreCase(_name, "content-type")
                        || __moduleCfg.isTransferHeaderEnabled()
                                && (!__moduleCfg.getTransferHeaderBlackList().isEmpty()
                                        && !__moduleCfg.getTransferHeaderBlackList().contains(_name)
                                        || !__moduleCfg.getTransferHeaderWhiteList().isEmpty()
                                                && __moduleCfg.getTransferHeaderWhiteList().contains(_name))) {
                    _conn.setRequestProperty(_name, _value);
                    _flag = true;
                }
                //
                if (_LOG.isDebugEnabled()) {
                    _LOG.debug("--> [" + _threadId + "] \t " + (_flag ? " - " : " > ") + _name + ": " + _value);
                }
            }
            _conn.connect();
            //
            if (_postFlag) {
                DataOutputStream _output = new DataOutputStream(_conn.getOutputStream());
                try {
                    if (_multipartFlag) {
                        if (_LOG.isDebugEnabled()) {
                            _LOG.debug("--> [" + _threadId + "] Multipart: TRUE");
                        }
                        IOUtils.copyLarge(request.getInputStream(), _output);
                    } else {
                        String _charset = request.getCharacterEncoding();
                        String _queryStr = ParamUtils.buildQueryParamStr(request.getParameterMap(), true, _charset);
                        IOUtils.write(_queryStr, _output, _charset);
                        //
                        if (_LOG.isDebugEnabled()) {
                            _LOG.debug("--> [" + _threadId + "] Request Parameters: ");
                            Map<String, String> _paramsMap = ParamUtils.parseQueryParamStr(_queryStr, true,
                                    _charset);
                            for (Map.Entry<String, String> _param : _paramsMap.entrySet()) {
                                _LOG.debug("--> [" + _threadId + "] \t - " + _param.getKey() + ": "
                                        + _param.getValue());
                            }
                        }
                    }
                    _output.flush();
                } finally {
                    IOUtils.closeQuietly(_output);
                }
            }
            //
            int _code = _conn.getResponseCode();
            //
            if (_LOG.isDebugEnabled()) {
                _LOG.debug("--> [" + _threadId + "] Response Code: " + _code);
                _LOG.debug("--> [" + _threadId + "] Response Headers: ");
            }
            //
            Map<String, List<String>> _headers = _conn.getHeaderFields();
            for (Map.Entry<String, List<String>> _entry : _headers.entrySet()) {
                if (_entry.getKey() != null) {
                    boolean _flag = false;
                    String _values = StringUtils.join(_entry.getValue(), ",");
                    if (StringUtils.equalsIgnoreCase(_entry.getKey(), "content-type")
                            || __moduleCfg.isTransferHeaderEnabled()
                                    && !__moduleCfg.getResponseHeaderWhileList().isEmpty()
                                    && __moduleCfg.getResponseHeaderWhileList().contains(_entry.getKey())) {
                        response.setHeader(_entry.getKey(), _values);
                        _flag = true;
                    }
                    if (_LOG.isDebugEnabled()) {
                        _LOG.debug("--> [" + _threadId + "] \t " + (_flag ? " - " : " > ") + _entry.getKey() + ": "
                                + _values);
                    }
                }
            }
            if (HttpURLConnection.HTTP_BAD_REQUEST <= _conn.getResponseCode()) {
                response.sendError(_code);
            } else {
                if (HttpURLConnection.HTTP_OK == _code) {
                    InputStream _inputStream = _conn.getInputStream();
                    if (_inputStream != null) {
                        if (!_multipartFlag) {
                            byte[] _content = IOUtils.toByteArray(_inputStream);
                            IOUtils.write(_content, response.getOutputStream());
                            //
                            if (_LOG.isDebugEnabled()) {
                                _LOG.debug("--> [" + _threadId + "] Response Content: " + __doParseContentBody(
                                        _conn, _content, WebMVC.get().getModuleCfg().getDefaultCharsetEncoding()));
                            }
                        } else {
                            IOUtils.copyLarge(_conn.getInputStream(), response.getOutputStream());
                            //
                            if (_LOG.isDebugEnabled()) {
                                _LOG.debug("--> [" + _threadId + "] Response Content: MultipartBody");
                            }
                        }
                    } else if (_LOG.isDebugEnabled()) {
                        _LOG.debug("--> [" + _threadId + "] Response Content: NULL");
                    }
                    response.flushBuffer();
                } else {
                    InputStream _inputStream = _conn.getInputStream();
                    if (_inputStream != null) {
                        byte[] _content = IOUtils.toByteArray(_inputStream);
                        IOUtils.write(_content, response.getOutputStream());
                        //
                        if (_LOG.isDebugEnabled()) {
                            _LOG.debug("--> [" + _threadId + "] Response Content: " + __doParseContentBody(_conn,
                                    _content, WebMVC.get().getModuleCfg().getDefaultCharsetEncoding()));
                        }
                    } else if (_LOG.isDebugEnabled()) {
                        _LOG.debug("--> [" + _threadId + "] Response Content: NULL");
                    }
                    response.setStatus(_code);
                    response.flushBuffer();
                }
            }
        } catch (Throwable e) {
            _LOG.warn("An exception occurred while processing request mapping '" + url + "': ",
                    RuntimeUtils.unwrapThrow(e));
        } finally {
            IOUtils.close(_conn);
            //
            if (_LOG.isDebugEnabled()) {
                if (_consumeTime != null) {
                    _consumeTime.stop();
                    _LOG.debug("--> [" + _threadId + "] Total execution time: " + _consumeTime.getTime() + "ms");
                }
                _LOG.debug("-------------------------------------------------");
            }
        }
    }

    public void destroy() throws Exception {
        if (__inited) {
            __inited = false;
            //
            __moduleCfg = null;
            __owner = null;
        }
    }

    public YMP getOwner() {
        return __owner;
    }

    public IWebProxyModuleCfg getModuleCfg() {
        return __moduleCfg;
    }
}