Skip to content

Commit

Permalink
Fix MicroserviceChangeTrigger to send servlet response to remote server.
Browse files Browse the repository at this point in the history
  • Loading branch information
dewarim committed Nov 22, 2015
1 parent df87c70 commit 677b455
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 17 deletions.
2 changes: 1 addition & 1 deletion grails-app/conf/BuildConfig.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ grails.project.dependency.resolution = {
compile(':spring-security-core:2.0-RC5')
compile ":rest-client-builder:2.1.1"
compile (":twitter-bootstrap:3.2.0.2"){excludes 'svn'}
compile ":cinnamon-db:3.6.13"
compile ":cinnamon-db:3.6.20"
runtime ':tika-parser:1.3.0.1'
compile ":remote-pagination:0.3"
compile ":geb:${gebPluginVersion}"
Expand Down
3 changes: 2 additions & 1 deletion grails-app/conf/Config.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ log4j = {
'cinnamon.cinnamon.filters.TriggerFilters',
'cinnamon.index.indexer.ParentFolderPathIndexer',
'org.springframework.security.authentication',
'cinnamon.PreAuthenticatedAuthenticationProvider'
'cinnamon.PreAuthenticatedAuthenticationProvider',
'cinnamon.servlet.ResponseFilter'

debug 'grails.app.domain.cinnamon.index'
debug 'grails.app.controllers.cinnamon.FolderController'
Expand Down
27 changes: 15 additions & 12 deletions grails-app/conf/cinnamon/filters/TriggerFilters.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class TriggerFilters {
if (poBox.endProcessing) {
return
}
log.debug("executing trigger: " + changeTrigger.getTriggerType().getName());
log.debug("executing pre trigger: " + changeTrigger.getTriggerType().getName());
def trigger = changeTrigger.triggerType.triggerClass.newInstance();
poBox = trigger.executePreCommand(poBox, changeTrigger)
}
Expand All @@ -41,11 +41,14 @@ class TriggerFilters {
return true
}

// afterView = { (Exception exception ->
// if(exception != null){
// return true // do not apply any filters on exceptions.
// }
after = { Map model ->
afterView = { Exception exception ->

log.debug("afterView: controllerName: ${controllerName} / action: ${actionName}")

if(exception != null){
return true // do not apply any filters on exceptions.
}
// after = { Map model ->

def triggers = ChangeTrigger.findAll("""from ChangeTrigger ct where
ct.controller=:controller and
Expand All @@ -55,15 +58,15 @@ class TriggerFilters {
order by ct.ranking
""".replaceAll('\n', ' '), [controller: controllerName, action: actionName])

log.debug("model: "+model)
// log.debug("model: "+model)

PoBox poBox = new PoBox(request, response, userService.user, session.repositoryName, params, model,
PoBox poBox = new PoBox(request, response, userService.user, session.repositoryName, params, null,
controllerName, actionName, grailsApplication);
triggers.each { changeTrigger ->
if (poBox.endProcessing) {
return
}
log.debug("executing trigger: " + changeTrigger.getTriggerType().getName());
log.debug("executing post trigger: " + changeTrigger.getTriggerType().getName());
def trigger = changeTrigger.triggerType.triggerClass.newInstance();
poBox = trigger.executePostCommand(poBox, changeTrigger)
}
Expand All @@ -73,9 +76,9 @@ class TriggerFilters {
}
return true
}
afterView = { Exception e ->

}
// afterView = { Exception e ->
//
// }
}
}
}
6 changes: 3 additions & 3 deletions grails-app/controllers/cinnamon/TestController.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ class TestController {
if (!msg) {
msg = ""
}
return [msg: msg]
return [msg: msg, foo:'bar']
}

def microserviceChangeTriggerPreRequestTest(String msg) {
log.info("microserviceChangeTriggerPreRequestTest received: " + (msg?.encodeAsHTML()))
log.debug("Params: " + params)
response.setHeader("microservice-pre-test", "ok")
response.flushBuffer()
render(text:"")
}

def microserviceChangeTriggerPostRequestTest(String msg) {
log.info("microserviceChangeTriggerPreRequestTest received: " + (msg?.encodeAsHTML()))
log.info("microserviceChangeTriggerPostRequestTest received: " + (msg?.encodeAsHTML()))
log.debug("Params: " + params)
response.setHeader("microservice-post-test", "ok")
render(text: "<xml>Just a trigger result</xml>")
Expand Down
68 changes: 68 additions & 0 deletions src/java/cinnamon/servlet/HttpServletResponseCopier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package cinnamon.servlet;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

/**
* Based on: http://stackoverflow.com/questions/8933054/how-to-log-response-content-from-a-java-web-server
*/
public class HttpServletResponseCopier extends HttpServletResponseWrapper {

private ServletOutputStream outputStream;
private PrintWriter writer;
private ServletOutputStreamCopier copier;

public HttpServletResponseCopier(HttpServletResponse response) throws IOException {
super(response);
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}

if (outputStream == null) {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(outputStream);
}

return copier;
}

@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}

if (writer == null) {
copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
}

return writer;
}

@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
copier.flush();
}
}

public byte[] getCopy() {
if (copier != null) {
return copier.getCopy();
} else {
return new byte[0];
}
}

}
85 changes: 85 additions & 0 deletions src/java/cinnamon/servlet/ResponseFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package cinnamon.servlet;


import cinnamon.global.ConfThreadLocal;
import cinnamon.trigger.impl.MicroserviceChangeTrigger;
import org.apache.http.HeaderElement;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

/**
* Based on: http://stackoverflow.com/questions/8933054/how-to-log-response-content-from-a-java-web-server
*/
public class ResponseFilter implements Filter {

Logger log = LoggerFactory.getLogger(ResponseFilter.class);


@Override
public void init(FilterConfig config) throws ServletException {
// NOOP.
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (response.getCharacterEncoding() == null) {
response.setCharacterEncoding("UTF-8"); // Or whatever default. UTF-8 is good for World Domination.
}

HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);

try {
chain.doFilter(request, responseCopier);
responseCopier.flushBuffer();
} finally {
byte[] copy = responseCopier.getCopy();
log.debug("response.copy: " + new String(copy, "UTF-8"));

HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
for (String url : httpServletResponse.getHeaders("microservice")) {
// new MicroserviceChangeTrigger().executePostCommand()
HttpClient httpClient = HttpClientBuilder.create().build();
RequestBuilder requestCopy = RequestBuilder.create("POST");
requestCopy.setUri(url);
HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
if (headerName.equals("microservice")) {
continue;
}
requestCopy.setHeader(headerName, httpServletRequest.getHeader(headerName));
}
for (Map.Entry<String, String[]> entry : httpServletRequest.getParameterMap().entrySet()) {
for (String paramVal : entry.getValue()) {
requestCopy.addParameter(entry.getKey(), paramVal);
}
}

requestCopy.addParameter("cinnamonResponse", new String(copy, "UTF-8"));
HttpResponse httpResponse = httpClient.execute(requestCopy.build());
log.debug("Microservice response status:" + httpResponse.getStatusLine());
log.debug("Microservice response content:" + EntityUtils.toString(httpResponse.getEntity()));
}

}
}

@Override
public void destroy() {
// NOOP.
}
}
41 changes: 41 additions & 0 deletions src/java/cinnamon/servlet/ServletOutputStreamCopier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cinnamon.servlet;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* Based on: http://stackoverflow.com/questions/8933054/how-to-log-response-content-from-a-java-web-server
*/
public class ServletOutputStreamCopier extends ServletOutputStream {

private OutputStream outputStream;
private ByteArrayOutputStream copy;

public ServletOutputStreamCopier(OutputStream outputStream) {
this.outputStream = outputStream;
this.copy = new ByteArrayOutputStream(4096);
}

@Override
public void write(int b) throws IOException {
outputStream.write(b);
copy.write(b);
}

public byte[] getCopy() {
return copy.toByteArray();
}

@Override
public boolean isReady() {
return true;
}

@Override
public void setWriteListener(WriteListener writeListener) {

}
}
93 changes: 93 additions & 0 deletions src/templates/war/web.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
metadata-complete="true"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>/@grails.project.key@</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<context-param>
<param-name>webAppRootKey</param-name>
<param-value>@grails.project.key@</param-value>
</context-param>



<filter>
<filter-name>charEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>characterEncodingFilter</param-value>
</init-param>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>charEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>responseFilter</filter-name>
<filter-class>cinnamon.servlet.ResponseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>responseFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
<listener-class>org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener</listener-class>
</listener>

<!-- Grails dispatcher servlet -->
<servlet>
<servlet-name>grails</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet</servlet-class>
<init-param>
<param-name>dispatchOptionsRequest</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>

<!-- The Groovy Server Pages servlet -->
<servlet>
<servlet-name>gsp</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.pages.GroovyPagesServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>gsp</servlet-name>
<url-pattern>*.gsp</url-pattern>
</servlet-mapping>

<session-config>
<!-- 30 minutes -->
<session-timeout>30</session-timeout>
</session-config>

<welcome-file-list>
<!--
The order of the welcome pages is important. JBoss deployment will
break if index.gsp is first in the list.
-->
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.gsp</welcome-file>
</welcome-file-list>



</web-app>

0 comments on commit 677b455

Please sign in to comment.