📄 proxiedresponsedispatcher.java
字号:
/*
* SSL-Explorer
*
* Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package com.sslexplorer.replacementproxy;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.Cookie;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.sslexplorer.boot.ReplacementEngine;
import com.sslexplorer.boot.Replacer;
import com.sslexplorer.boot.RequestHandlerResponse;
import com.sslexplorer.boot.Util;
import com.sslexplorer.core.CoreServlet;
import com.sslexplorer.security.User;
import com.sslexplorer.webforwards.WebForwardTypes;
/**
* @author Brett Smith <brett@3sp.com>
*/
public class ProxiedResponseDispatcher {
final static Log log = LogFactory.getLog(ProxiedResponseDispatcher.class);
private RequestProcessor requestProcessor;
private ProxiedResponseProcessor responseProcessor;
private RequestHandlerResponse response;
private User user;
private ContentCache cache;
private SimpleDateFormat sdf;
public ProxiedResponseDispatcher(RequestProcessor requestProcessor, ProxiedResponseProcessor responseProcessor,
RequestHandlerResponse response, User user, ContentCache cache) {
this.responseProcessor = responseProcessor;
this.requestProcessor = requestProcessor;
this.response = response;
this.cache = cache;
this.user = user;
sdf = new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss zzz");
}
public void sendResponse() throws Exception {
// Only set the content type for the response if the target server
// returned it
String type = responseProcessor.getContentType();
if (type == null) {
// If the mime type is not returned, then guess it from our own map
type = requestProcessor.getSession().getServletContext().getMimeType(
responseProcessor.getRequestDispatcher().getConnectionURL().getFile());
if (log.isDebugEnabled())
log.debug("Guessed response type " + type + " from URL");
}
else {
if (log.isDebugEnabled())
log.debug("Sending response of type " + type);
}
if (type != null) {
response.setField("Content-Type", type);
}
int code = responseProcessor.getRequestDispatcher().getResponseCode();
if (log.isDebugEnabled())
log.debug("Sending response code " + code);
response.setStatus(code);
// Configure replacement proxy content encoding
if(requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING)) {
if(responseProcessor.getCharset() != null) {
response.setCharacterEncoding(responseProcessor.getCharset());
}
} else
response.setCharacterEncoding(requestProcessor.getWebForward().getEncoding());
// Add all of the headers to the response
for (Iterator i = responseProcessor.getHeaders().iterator(); i.hasNext();) {
Header hi = (Header) i.next();
response.setField(hi.getName(), hi.getVal());
}
//
OutputStream responseOut = null;
if (responseProcessor.isCacheable()) {
if (log.isDebugEnabled())
log.debug("Opening output stream via a cache");
responseOut = new CacheingOutputStream(response.getOutputStream(), responseProcessor.getContentLength() == -1 ? 1024
: responseProcessor.getContentLength(), responseProcessor.getHeaders(), type);
} else {
if (log.isDebugEnabled())
log.debug("Opening non-cached output stream");
responseOut = response.getOutputStream();
}
//
InputStream serverIn = responseProcessor.getProxiedInputStream();
if (serverIn != null) {
// Get just type mime type part of the content type
String mimeType = type;
int idx = mimeType == null ? -1 : mimeType.indexOf(";");
if (idx != -1) {
mimeType = mimeType.substring(0, idx);
}
// If there is no content type or are no replaces
URL connectionURL = responseProcessor.getRequestDispatcher().getConnectionURL();
List replacements = CoreServlet.getServlet().getSystemDatabase().getReplacementsForContent(
user.getPrincipalName(), Replacement.REPLACEMENT_TYPE_RECEIVED_CONTENT, mimeType,
connectionURL.toExternalForm());
if (replacements.size() > 0) {
// The default replacer
if (log.isDebugEnabled())
log.debug("Found " + replacements.size() + ", processing");
ReplacementEngine replace = new ReplacementEngine();
if(!requestProcessor.getWebForward().getEncoding().equals(WebForwardTypes.DEFAULT_ENCODING))
replace.setEncoding(requestProcessor.getWebForward().getEncoding());
else
replace.setEncoding(responseProcessor.getCharset());
replace.setCaseSensitive(false);
replace.setDotAll(true);
final BaseSearch baseSearch = new BaseSearch();
replace.addPattern("(<base*\\s+(?:href)\\=['\\\"]*)([^\\s'>\\\"]*)([^>]*)(>)", baseSearch, "");
Replacer replacer = new ProxyReplacer(requestProcessor, baseSearch);
for (Iterator i = replacements.iterator(); i.hasNext();) {
Replacement r = (Replacement) i.next();
if (log.isDebugEnabled())
log.debug("Adding replacement pattern '" + r.getMatchPattern() + "' = '" + r.getReplacePattern() + "'");
if (r.getReplacePattern().startsWith("#")) {
String cn = r.getReplacePattern().substring(1);
try {
Class clazz = Class.forName(cn);
Constructor c = clazz.getConstructor(new Class[] { URL.class, String.class });
Replacer re = (Replacer) (c.newInstance(new Object[] { requestProcessor.getContext(), requestProcessor.getUniqueTicket() }));
if (log.isDebugEnabled())
log.debug("Loaded custom replacer " + cn + ".");
replace.addPattern(r.getMatchPattern(), re, null);
} catch (Throwable t) {
log.error("Could not load custom replacer " + cn + ".", t);
}
} else {
replace.addPattern(r.getMatchPattern(), replacer, r.getReplacePattern());
}
}
OutputStream monitorOut = responseOut;
int origLen = responseProcessor.getContentLength();
int len = origLen == -1 ? 1024 : responseProcessor.getContentLength();
if (log.isDebugEnabled())
log.debug("Reading response from target and processing into memory (" + len + " bytes buffer)");
monitorOut = new ByteArrayOutputStream(len);
long length = replace.replace(serverIn, monitorOut);
if (log.isDebugEnabled())
log.debug("Replacement complete, getting new Written the responseReading response from target into memory ready for replacement (" + len + " bytes)");
if (origLen != -1) {
if (log.isDebugEnabled())
log.debug("New output length is " + length);
response.setContentLength((int) length);
}
if (log.isDebugEnabled())
log.debug("Writing respone back to client");
responseOut.write(((ByteArrayOutputStream) monitorOut).toByteArray());
} else {
if (log.isDebugEnabled())
log.debug("Just copying content type of " + type);
Util.copy(serverIn, responseOut);
}
if (log.isDebugEnabled()) {
// Cache the response
if (responseProcessor.isCacheable()) {
log.debug("Caching page "
+ requestProcessor.getConnectionPath()
+ (responseProcessor.getCacheExpiryDate() == null ? " (never expires)" : (" (expires on " + sdf
.format(responseProcessor.getCacheExpiryDate()))) + ")");
if (!cache.store(requestProcessor.getConnectionPath(), (CacheingOutputStream) responseOut, responseProcessor
.getCacheExpiryDate() == null ? null : new Long(responseProcessor.getCacheExpiryDate().getTime()),
null)) {
log.warn("Failed to cache page " + requestProcessor.getConnectionPath());
} else {
log.debug("Cached page " + requestProcessor.getConnectionPath());
}
} else {
log.debug("Removing " + requestProcessor.getConnectionPath() + " from cache");
cache.clear(requestProcessor.getConnectionPath());
}
}
} else {
throw new Exception("No streams.");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -