Last active
December 31, 2023 12:59
-
-
Save maciejwalkowiak/17b4295f0e77565375dd50172b416566 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.ByteArrayOutputStream; | |
import java.io.IOException; | |
import java.io.OutputStreamWriter; | |
import java.io.PrintWriter; | |
import jakarta.servlet.ServletOutputStream; | |
import jakarta.servlet.WriteListener; | |
import jakarta.servlet.http.HttpServletResponse; | |
import jakarta.servlet.http.HttpServletResponseWrapper; | |
class CapturingResponseWrapper extends HttpServletResponseWrapper { | |
private final ByteArrayOutputStream capture; | |
private ServletOutputStream output; | |
private PrintWriter writer; | |
public CapturingResponseWrapper(HttpServletResponse response) { | |
super(response); | |
capture = new ByteArrayOutputStream(response.getBufferSize()); | |
} | |
@Override | |
public ServletOutputStream getOutputStream() { | |
if (writer != null) { | |
throw new IllegalStateException("getWriter() has already been called on this response."); | |
} | |
if (output == null) { | |
output = new ServletOutputStream() { | |
@Override public boolean isReady() { | |
return true; | |
} | |
@Override public void setWriteListener(WriteListener writeListener) { | |
} | |
@Override | |
public void write(int b) throws IOException { | |
capture.write(b); | |
} | |
@Override | |
public void flush() throws IOException { | |
capture.flush(); | |
} | |
@Override | |
public void close() throws IOException { | |
capture.close(); | |
} | |
}; | |
} | |
return output; | |
} | |
@Override | |
public PrintWriter getWriter() throws IOException { | |
if (output != null) { | |
throw new IllegalStateException("getOutputStream() has already been called on this response."); | |
} | |
if (writer == null) { | |
writer = new PrintWriter(new OutputStreamWriter(capture, getCharacterEncoding())); | |
} | |
return writer; | |
} | |
@Override | |
public void flushBuffer() throws IOException { | |
super.flushBuffer(); | |
if (writer != null) { | |
writer.flush(); | |
} else if (output != null) { | |
output.flush(); | |
} | |
} | |
public byte[] getCaptureAsBytes() throws IOException { | |
if (writer != null) { | |
writer.close(); | |
} else if (output != null) { | |
output.close(); | |
} | |
return capture.toByteArray(); | |
} | |
public String getCaptureAsString() throws IOException { | |
return new String(getCaptureAsBytes(), getCharacterEncoding()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.maciejwalkowiak.just.spring.boot.livereload.jakarta; | |
import java.io.IOException; | |
import jakarta.servlet.Filter; | |
import jakarta.servlet.FilterChain; | |
import jakarta.servlet.ServletException; | |
import jakarta.servlet.ServletRequest; | |
import jakarta.servlet.ServletResponse; | |
import jakarta.servlet.http.HttpServletResponse; | |
import org.springframework.http.MediaType; | |
class LiveReloadScriptFilter implements Filter { | |
private final String scriptSnippet; | |
LiveReloadScriptFilter(int liveReloadPort, int justServerPort) { | |
this.scriptSnippet = String.format( | |
"<script src=\"http://localhost:%d/livereload/livereload.js?port=%d&host=localhost\"></script>", justServerPort, | |
liveReloadPort); | |
} | |
@Override | |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) | |
throws IOException, ServletException { | |
CapturingResponseWrapper capturingResponseWrapper = new CapturingResponseWrapper((HttpServletResponse) response); | |
filterChain.doFilter(request, capturingResponseWrapper); | |
String contentType = capturingResponseWrapper.getContentType(); | |
String content = capturingResponseWrapper.getCaptureAsString(); | |
if ((contentType != null) && MediaType.TEXT_HTML.isCompatibleWith(MediaType.parseMediaType(contentType))) { | |
String alreadyFilteredAttributeName = this.getAlreadyFilteredAttributeName(); | |
boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null; | |
if (!hasAlreadyFilteredAttribute) { | |
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE); | |
response.getWriter().write(content + this.scriptSnippet); | |
} else { | |
response.getWriter().write(content); | |
} | |
} else { | |
response.getWriter().write(content); | |
} | |
} | |
protected String getAlreadyFilteredAttributeName() { | |
String name = this.getClass().getName(); | |
return name + ".FILTERED"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment