145 lines
4.4 KiB
Java
145 lines
4.4 KiB
Java
package com.minicircuits;
|
|
|
|
import java.io.BufferedInputStream;
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.io.PrintWriter;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
|
|
import javax.servlet.ServletOutputStream;
|
|
import javax.servlet.WriteListener;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpServletResponseWrapper;
|
|
|
|
public class BufferedResponseWrapper extends HttpServletResponseWrapper {
|
|
private final Path tempFile;
|
|
private final FileOutputStream fileOutputStream;
|
|
private final ServletOutputStream servletOutputStream;
|
|
private PrintWriter writer;
|
|
|
|
public BufferedResponseWrapper(HttpServletResponse response) throws IOException {
|
|
super(response);
|
|
this.tempFile = Files.createTempFile("fetchapi_", ".tmp");
|
|
this.fileOutputStream = new FileOutputStream(tempFile.toFile());
|
|
this.servletOutputStream = new ServletOutputStream() {
|
|
@Override
|
|
public void write(int b) throws IOException {
|
|
fileOutputStream.write(b);
|
|
}
|
|
|
|
@Override
|
|
public void write(byte[] b, int off, int len) throws IOException {
|
|
fileOutputStream.write(b, off, len);
|
|
}
|
|
|
|
@Override
|
|
public void flush() throws IOException {
|
|
fileOutputStream.flush();
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
fileOutputStream.close();
|
|
}
|
|
|
|
@Override
|
|
public boolean isReady() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void setWriteListener(WriteListener writeListener) {
|
|
// Not used for blocking I/O
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public ServletOutputStream getOutputStream() {
|
|
return servletOutputStream;
|
|
}
|
|
|
|
@Override
|
|
public PrintWriter getWriter() throws IOException {
|
|
if (writer == null) {
|
|
String charset = getCharacterEncoding();
|
|
writer = new PrintWriter(new OutputStreamWriter(fileOutputStream,
|
|
charset != null ? charset : "UTF-8"));
|
|
}
|
|
return writer;
|
|
}
|
|
|
|
@Override
|
|
public void flushBuffer() {
|
|
// Don't flush to the real response — we're buffering
|
|
}
|
|
|
|
@Override
|
|
public void reset() {
|
|
// Don't reset the real response during buffering
|
|
}
|
|
|
|
@Override
|
|
public void resetBuffer() {
|
|
// Don't reset during buffering
|
|
}
|
|
|
|
/**
|
|
* Flush any remaining data, then stream the temp file to the real response.
|
|
* Sets Content-Length. Deletes the temp file when done.
|
|
*/
|
|
public void writeToResponse() throws IOException {
|
|
// Flush and close writer/stream
|
|
if (writer != null) {
|
|
writer.close();
|
|
} else {
|
|
fileOutputStream.close();
|
|
}
|
|
|
|
// Set content length from temp file size
|
|
long fileSize = Files.size(tempFile);
|
|
if (fileSize <= Integer.MAX_VALUE) {
|
|
getResponse().setContentLength((int) fileSize);
|
|
} else {
|
|
((HttpServletResponse) getResponse()).setHeader("Content-Length", Long.toString(fileSize));
|
|
}
|
|
|
|
// Stream temp file to real response
|
|
HttpServletResponse realResponse = (HttpServletResponse) getResponse();
|
|
try (InputStream in = new BufferedInputStream(new FileInputStream(tempFile.toFile()), 32768);
|
|
OutputStream out = new BufferedOutputStream(realResponse.getOutputStream(), 32768)) {
|
|
byte[] buffer = new byte[32768];
|
|
int bytesRead;
|
|
while ((bytesRead = in.read(buffer)) != -1) {
|
|
out.write(buffer, 0, bytesRead);
|
|
}
|
|
out.flush();
|
|
} finally {
|
|
// Always delete the temp file
|
|
Files.deleteIfExists(tempFile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up temp file if writeToResponse was never called (e.g., on error).
|
|
*/
|
|
public void cleanup() {
|
|
try {
|
|
if (fileOutputStream != null) {
|
|
fileOutputStream.close();
|
|
}
|
|
} catch (IOException ignored) {
|
|
}
|
|
try {
|
|
Files.deleteIfExists(tempFile);
|
|
} catch (IOException ignored) {
|
|
}
|
|
}
|
|
}
|