Skip to content
Merged

setBody #2462

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private Outcome handleInternal(Exchange exchange, Flow flow) {
internal(getRouter().isProduction(), getDisplayName())
.title("Error evaluating expression!")
.internal("field", fieldName)
.internal("value", expression)
.internal("expression", expression)
.exception(root)
.stacktrace(false)
.buildAndSetResponse(exchange);
Expand All @@ -70,10 +70,6 @@ private Outcome handleInternal(Exchange exchange, Flow flow) {
return CONTINUE;
}

/**
*
* @return
*/
protected abstract Class<?> getExpressionReturnType();

protected abstract boolean shouldSetValue(Exchange exchange, Flow flow);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.predic8.membrane.core.interceptor.lang;

import com.predic8.membrane.annot.*;
import com.predic8.membrane.core.exchange.*;
import com.predic8.membrane.core.interceptor.*;
import com.predic8.membrane.core.util.*;
import org.slf4j.*;

import static com.predic8.membrane.core.exceptions.ProblemDetails.*;
import static com.predic8.membrane.core.interceptor.Interceptor.Flow.*;
import static com.predic8.membrane.core.interceptor.Outcome.*;
import static com.predic8.membrane.core.interceptor.Outcome.ABORT;
import static java.nio.charset.StandardCharsets.*;

/**
* setBody sets the content of the HTTP message body to the specified value. The value
* can be a static string, or it can be dynamically generated by an expression.
* Different languages such as SpEL, Groovy, XMLPath or JsonPath are supported.
* setBody does not support conditional processing or loops. When you need these features,
* resort to the template plugin instead.
*
* The content of the message body is set as UTF-8 encoded bytes. Set a corresponding content type header if necessary.
*/
@MCElement(name = "setBody")
public class SetBodyInterceptor extends AbstractExchangeExpressionInterceptor {

private static final Logger log = LoggerFactory.getLogger(SetBodyInterceptor.class);

@Override
public Outcome handleRequest(Exchange exc) {
return handleInternal(exc, REQUEST);
}

@Override
public Outcome handleResponse(Exchange exc) {
return handleInternal(exc, RESPONSE);
}

private Outcome handleInternal(Exchange exchange, Flow flow) {
try {
// The value is typically set from YAML there we can assume UTF-8
var result = exchangeExpression.evaluate(exchange, flow, String.class);
if (result == null) {
result = "null";
}
exchange.getMessage(flow).setBodyContent(result.getBytes(UTF_8));
return CONTINUE;
} catch (Exception e) {
var root = ExceptionUtil.getRootCause(e);
var message = "While evaluating expression %s: %s".formatted(expression, root.getMessage());
log.info(message);

internal(getRouter().isProduction(), getDisplayName())
.title("Error evaluating expression!")
.internal("expression", expression)
.exception(root)
.stacktrace(false)
Comment thread
predic8 marked this conversation as resolved.
.buildAndSetResponse(exchange);
return ABORT;
}
}

/**
* Sets the expression to be evaluated for modifying the HTTP message body.
* The provided string value can represent a static text or a dynamic expression
*
* @param value expression or static string
*/
@MCAttribute
public void setValue(String value) {
this.expression = value;
}

public String getValue() {
return expression;
}

@Override
public String getDisplayName() {
return "setBody";
}

@Override
public String getShortDescription() {
return "Sets the content of the HTTP message body to the expression: %s.".formatted(expression);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum Language {GROOVY, SPEL, XPATH, JSONPATH}
static ExchangeExpression expression(Interceptor interceptor, Language language, String expression) {
return switch (language) {
case GROOVY -> new GroovyExchangeExpression(interceptor, expression);
case SPEL -> new SpELExchangeExpression(expression,null);
case SPEL -> new SpELExchangeExpression(expression,null); // parserContext is null on purpose ${} or #{} are not needed here
case XPATH -> new XPathExchangeExpression(interceptor,expression);
case JSONPATH -> new JsonpathExchangeExpression(expression);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,18 @@
limitations under the License. */
package com.predic8.membrane.core.lang;

import com.predic8.membrane.core.*;
import com.predic8.membrane.core.exchange.*;
import com.predic8.membrane.core.interceptor.*;
import com.predic8.membrane.core.interceptor.Interceptor.*;
import com.predic8.membrane.core.lang.spel.*;

import org.slf4j.*;

import java.util.*;
import java.util.regex.*;

import static com.predic8.membrane.core.lang.ExchangeExpression.Language.*;
import static com.predic8.membrane.core.lang.ExchangeExpression.expression;
import static com.predic8.membrane.core.lang.ExchangeExpression.*;
import static com.predic8.membrane.core.lang.spel.DollarTemplateParserContext.*;
Comment thread
predic8 marked this conversation as resolved.

public class TemplateExchangeExpression extends AbstractExchangeExpression {

Expand All @@ -41,7 +40,7 @@ public class TemplateExchangeExpression extends AbstractExchangeExpression {
public static ExchangeExpression newInstance(Interceptor interceptor, Language language, String expression) {
// SpEL comes with its own templating
if (language == SPEL) {
return new SpELExchangeExpression(expression, new SpELExchangeExpression.DollarBracketTemplateParserContext());
return new SpELExchangeExpression(expression, DOLLAR_TEMPLATE_PARSER_CONTEXT);
}
return new TemplateExchangeExpression(interceptor, language, expression);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.predic8.membrane.core.lang.spel;

import org.springframework.expression.common.*;

public class DollarTemplateParserContext extends TemplateParserContext {

public static final DollarTemplateParserContext DOLLAR_TEMPLATE_PARSER_CONTEXT = new DollarTemplateParserContext();

private DollarTemplateParserContext() {
super("${", "}");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,4 @@ static boolean toBoolean(Object o) {
private @NotNull SpelParserConfiguration getSpelParserConfiguration() {
return new SpelParserConfiguration(MIXED, this.getClass().getClassLoader());
}

public static class DollarBracketTemplateParserContext extends TemplateParserContext {
public DollarBracketTemplateParserContext() {
super("${","}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.predic8.membrane.core.interceptor.lang;

import com.predic8.membrane.core.*;
import com.predic8.membrane.core.exchange.*;
import com.predic8.membrane.core.http.*;
import org.junit.jupiter.api.*;

import java.net.*;

import static com.predic8.membrane.core.http.Response.notImplemented;
import static org.junit.jupiter.api.Assertions.*;

/**
* A simple test is enough to test the logic of the interceptor.
* Complex expressions are tested in the ExchangeExpressionTest, and ...
*/
class SetBodyInterceptorTest {
Comment thread
predic8 marked this conversation as resolved.

private SetBodyInterceptor sbi;
private Exchange exc;

@BeforeEach
void setup() throws URISyntaxException {
sbi = new SetBodyInterceptor();

exc = Request.get("/foo").buildExchange();
exc.setResponse(notImplemented().body("bar").build());
}

@Test
void nullResult() {
sbi.setValue("null");
sbi.init(new Router());
sbi.handleRequest(exc);
assertEquals("null", exc.getRequest().getBodyAsStringDecoded());
}

@Test
void evalOfSimpleExpression() {
sbi.setValue("${path}");
sbi.init(new Router());
sbi.handleRequest(exc);
assertEquals("/foo", exc.getRequest().getBodyAsStringDecoded());
}

@Test
void response() {
sbi.setValue("SC: ${statusCode}");
sbi.init(new Router());
sbi.handleResponse(exc);
assertEquals("SC: 501", exc.getResponse().getBodyAsStringDecoded());
}
}
Loading