Ho bisogno di un filtro servlet che acquisisca tutto l'input, quindi maneggi quell'input, inserendo un token speciale in ogni forma. Immagina che il filtro sia legato a tutte le richieste (ad esempio url-pattern=*
). Ho il codice per l'acquisizione dei contenuti, ma non sembra che lo RequestWrapper
sia abbastanza robusto da catturare tutto l'input. Alcuni input restituiscono zero byte e quindi non posso "trasmettere" il contenuto all'utente. Ad esempio, stiamo ancora utilizzando Struts 1.3.10 e qualsiasi codice Struts non "cattura" correttamente, otteniamo zero byte di contenuto. Credo che sia a causa di come Struts maneggia in avanti. Se c'è un forward coinvolto nella richiesta, mi chiedo se il codice di cattura qui sotto funzionerà. Ecco tutto il codice, hai un approccio che catturerà qualsiasi tipo di contenuto destinato allo streaming all'utente.Il filtro servlet catch-all che dovrebbe acquisire TUTTO il contenuto di input HTML per la manipolazione, funziona solo a intermittenza
<filter>
<filter-name>Filter</filter-name>
<filter-class>mybrokenCaptureHtml.TokenFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
package mybrokenCaptureHtml;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class TokenFilter implements Filter {
@Override
public void destroy() {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
try {
final MyResponseWrapper responseWrapper = new MyResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, responseWrapper);
// **HERE DEPENDING ON THE SERVLET OR APPLICATION CODE (STRUTS, WICKET), the response returns an empty string //
// Especiall struts, is there something in their forwards that would cause an error?
final byte [] bytes = responseWrapper.toByteArray();
// For some applications that hit this filter
// ZERO BYTE DATA is returned, this is bad, but SOME
// CODE, the data is captured.
final String origHtml = new String(bytes);
final String newHtml = origHtml.replaceAll("(?i)</(\\s)*form(\\s)*>", "<input type=\"hidden\" name=\"zval\" value=\"fromSiteZ123\"/></form>");
response.getOutputStream().write(newHtml.getBytes());
} catch(final Exception e) {
e.printStackTrace();
}
return;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
static class MyResponseWrapper extends HttpServletResponseWrapper {
private final MyPrintWriter pw = new MyPrintWriter();
public byte [] toByteArray() {
return pw.toByteArray();
}
public MyResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public PrintWriter getWriter() {
return pw.getWriter();
}
@Override
public ServletOutputStream getOutputStream() {
return pw.getStream();
}
private static class MyPrintWriter {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PrintWriter pw = new PrintWriter(baos);
private ServletOutputStream sos = new MyServletStream(baos);
public PrintWriter getWriter() {
return pw;
}
public ServletOutputStream getStream() {
return sos;
}
byte[] toByteArray() {
return baos.toByteArray();
}
}
private static class MyServletStream extends ServletOutputStream {
ByteArrayOutputStream baos;
MyServletStream(final ByteArrayOutputStream baos) {
this.baos = baos;
}
@Override
public void write(final int param) throws IOException {
baos.write(param);
}
}
}
}
Questo è ciò che un esempio Struts app può sembrare, per alcune applicazioni (non Struts), possiamo catturare il contenuto. Ma per app come quella qui sotto, vengono restituiti zero byte per il contenuto HTML, ma dovrebbero esserci dei contenuti.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-nested.tld" prefix="nested"%>
<html:html>
<head>
<title><bean:message key="myApp.customization.title" /></title>
<LINK rel="stylesheet" type="text/css" href="../theme/styles.css">
</head>
<body>
<html:form styleId="customizemyAppForm" method="post" action="/customizemyApp.do?step=submit">
<html:submit onclick="javascript:finish(this.form);" styleClass="input_small"> <bean:message key="myApp.customization.submit" /> </html:submit>
<input type="button" styleClass="input_small" width="80" style="WIDTH:80px" name="<bean:message key="myApp.customization.cancel" />" value="<bean:message key="myApp.customization.cancel" />" onclick="javascript:cancel();">
</html:form>
</body>
</html:html>
Ho il sospetto che il MyResponseWrapper
e MyPrintWriter
non sono abbastanza robusto per catturare tutti i tipi di contenuti.
Esempio servlet che avrebbe funzionato (un):
response.getOutputStream().write(str.getBytes());
Esempio servlet che non avrebbe funzionato (B):
response.getWriter().println("<html>data</html>");
Esempio un otterrebbe una cattura, esempio b non lo faranno.
Ecco una classe wrapper migliorata, la maggior parte delle applicazioni funzionerà, ma ora alcune delle applicazioni struts, solo una parte della risposta viene inviata al browser.
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class ByteArrayResponseWrapper extends HttpServletResponseWrapper {
private PrintWriter output = null;
private ServletOutputStream outStream = null;
private static final String NL = System.getProperty("line.separator");
public ByteArrayResponseWrapper(final HttpServletResponse response) {
super(response);
}
public String getDocument() {
InputStream in = null;
try {
in = this.getInputStream();
if (in != null) {
return getDocument(in);
}
} catch(final Exception ee) {
// ee.print;StackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
//e.prin;tStackTrace();
}
}
}
return "";
}
protected String getDocument(final InputStream in) {
final StringBuffer buf = new StringBuffer();
BufferedReader br = null;
try {
String line = "";
br = new BufferedReader(new InputStreamReader(getInputStream(), this.getCharacterEncoding()));
while ((line = br.readLine()) != null) {
buf.append(line).append(NL);
}
} catch(final IOException e) {
//e.print;StackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException ex) {
}
}
return buf.toString();
}
@Override
public PrintWriter getWriter() throws IOException {
if (output == null) {
output = new PrintWriter(new OutputStreamWriter(getOutputStream(), this.getCharacterEncoding()));
}
return output;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (outStream == null) {
outStream = new BufferingServletOutputStream();
}
return outStream;
}
public InputStream getInputStream() throws IOException {
final BufferingServletOutputStream out = (BufferingServletOutputStream) getOutputStream();
return new ByteArrayInputStream(out.getBuffer().toByteArray());
}
/**
* Implementation of ServletOutputStream that handles the in-memory
* buffering of the response content
*/
public static class BufferingServletOutputStream extends ServletOutputStream {
ByteArrayOutputStream out = null;
public BufferingServletOutputStream() {
this.out = new ByteArrayOutputStream();
}
public ByteArrayOutputStream getBuffer() {
return out;
}
public void write(int b) throws IOException {
out.write(b);
}
public void write(byte[] b) throws IOException {
out.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
}
@Override
public void close() throws IOException {
out.close();
super.close();
}
@Override
public void flush() throws IOException {
out.flush();
super.flush();
}
}
}
ho trovato una possibile soluzione, nel metodo getInputStream
, sembra che se io chiamo 'stretta' su tutti gli oggetti, ad esempio outStream.flush()
e outStream.close()
e poi out.flush()
e out.close()
... Sembra che la finale i byte vengono scritti correttamente. non è intuitivo, ma sembra che funzioni.
ci mostrano come si registra il filtro. –
Aggiunto in alto, la parte del filtro funziona, la cattura è il pezzo rotto. –
Quindi, in pratica, vuoi catturare tutti i messaggi del form di Struts e manipolarlo? Che dire dei file caricati (ho bisogno di chiarezza su ciò che stai cercando di ottenere)? Non dimenticare che Struts mappa tutti gli attributi del tuo form agli attributi 'ActionForm'. Se funziona, non ci dovrebbero essere problemi. –