Browse Source

Updates ShortcutConfigurable to use custom EvaluationContext.

It uses a SimpleEvaluationContext as a delegate that adds a BeanResolver for bean references in SpEL.
pull/2709/head
spencergibb 3 years ago committed by spencergibb
parent
commit
bec3dc0e68
No known key found for this signature in database
GPG Key ID: 7788A47380690861
  1. 85
      spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ShortcutConfigurable.java
  2. 19
      spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ShortcutConfigurableTests.java

85
spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ShortcutConfigurable.java

@ -25,10 +25,21 @@ import java.util.stream.Collectors; @@ -25,10 +25,21 @@ import java.util.stream.Collectors;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.ConstructorResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.MethodResolver;
import org.springframework.expression.OperatorOverloader;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypeComparator;
import org.springframework.expression.TypeConverter;
import org.springframework.expression.TypeLocator;
import org.springframework.expression.TypedValue;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -54,8 +65,7 @@ public interface ShortcutConfigurable { @@ -54,8 +65,7 @@ public interface ShortcutConfigurable {
}
if (rawValue != null && rawValue.startsWith("#{") && entryValue.endsWith("}")) {
// assume it's spel
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new BeanFactoryResolver(beanFactory));
GatewayEvaluationContext context = new GatewayEvaluationContext(new BeanFactoryResolver(beanFactory));
Expression expression = parser.parseExpression(entryValue, new TemplateParserContext());
value = expression.getValue(context);
}
@ -148,4 +158,73 @@ public interface ShortcutConfigurable { @@ -148,4 +158,73 @@ public interface ShortcutConfigurable {
}
class GatewayEvaluationContext implements EvaluationContext {
private final BeanFactoryResolver beanFactoryResolver;
private SimpleEvaluationContext delegate = SimpleEvaluationContext.forReadOnlyDataBinding().build();
public GatewayEvaluationContext(BeanFactoryResolver beanFactoryResolver) {
this.beanFactoryResolver = beanFactoryResolver;
}
@Override
public TypedValue getRootObject() {
return delegate.getRootObject();
}
@Override
public List<PropertyAccessor> getPropertyAccessors() {
return delegate.getPropertyAccessors();
}
@Override
public List<ConstructorResolver> getConstructorResolvers() {
return delegate.getConstructorResolvers();
}
@Override
public List<MethodResolver> getMethodResolvers() {
return delegate.getMethodResolvers();
}
@Override
@Nullable
public BeanResolver getBeanResolver() {
return this.beanFactoryResolver;
}
@Override
public TypeLocator getTypeLocator() {
return delegate.getTypeLocator();
}
@Override
public TypeConverter getTypeConverter() {
return delegate.getTypeConverter();
}
@Override
public TypeComparator getTypeComparator() {
return delegate.getTypeComparator();
}
@Override
public OperatorOverloader getOperatorOverloader() {
return delegate.getOperatorOverloader();
}
@Override
public void setVariable(String name, Object value) {
delegate.setVariable(name, value);
}
@Override
@Nullable
public Object lookupVariable(String name) {
return delegate.lookupVariable(name);
}
}
}

19
spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ShortcutConfigurableTests.java

@ -30,10 +30,12 @@ import org.springframework.boot.SpringBootConfiguration; @@ -30,10 +30,12 @@ import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType;
import org.springframework.context.annotation.Bean;
import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@RunWith(SpringRunner.class)
@SpringBootTest
@ -44,6 +46,23 @@ public class ShortcutConfigurableTests { @@ -44,6 +46,23 @@ public class ShortcutConfigurableTests {
private SpelExpressionParser parser;
@Test
public void testNormalizeDefaultTypeWithSpelAndInvalidInputFails() {
parser = new SpelExpressionParser();
ShortcutConfigurable shortcutConfigurable = new ShortcutConfigurable() {
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("bean", "arg1");
}
};
Map<String, String> args = new HashMap<>();
args.put("bean", "#{T(java.lang.Runtime).getRuntime().exec(\"touch /tmp/x\")}");
args.put("arg1", "val1");
assertThatThrownBy(() -> {
ShortcutType.DEFAULT.normalize(args, shortcutConfigurable, parser, this.beanFactory);
}).isInstanceOf(SpelEvaluationException.class);
}
@Test
public void testNormalizeDefaultTypeWithSpel() {
parser = new SpelExpressionParser();

Loading…
Cancel
Save