Skip to content
This repository was archived by the owner on Mar 13, 2021. It is now read-only.

Commit 4dcd1ac

Browse files
David Turanskitrisberg
authored andcommitted
Enhance URL parsing and fix doc (#120)
This fixes some minor issues, replacing the `function.uri` regex with `java.net.URL` parsing. * Accepts main without handler `file:/target/my.jar?main=functions.App` technically not required for `@SpringBootApplication` but does not result in error * Accepts `handler` and `main` parameters in any order * Protocol defaults to `file:` if not provided.
1 parent 45fc0c4 commit 4dcd1ac

2 files changed

Lines changed: 115 additions & 25 deletions

File tree

src/main/java/io/projectriff/invoker/FunctionEnvironmentPostProcessor.java

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,10 +15,14 @@
1515
*/
1616
package io.projectriff.invoker;
1717

18+
import java.net.MalformedURLException;
19+
import java.net.URL;
20+
import java.net.URLConnection;
21+
import java.net.URLStreamHandler;
22+
import java.net.URLStreamHandlerFactory;
1823
import java.util.HashMap;
1924
import java.util.Map;
20-
import java.util.regex.Matcher;
21-
import java.util.regex.Pattern;
25+
import java.util.stream.Stream;
2226

2327
import org.springframework.boot.SpringApplication;
2428
import org.springframework.boot.env.EnvironmentPostProcessor;
@@ -30,42 +34,78 @@
3034

3135
/**
3236
* Convert the function.uri into properties that can be consumed by the deployer library.
33-
*
34-
* @author Dave Syer
3537
*
38+
* @author Dave Syer
39+
* @author David Turanski
3640
*/
3741
public class FunctionEnvironmentPostProcessor implements EnvironmentPostProcessor {
3842

39-
private static Pattern uriPattern = Pattern.compile("(.+)\\?.*handler=([^&]+)&?(.*)");
40-
4143
private static final String PROPERTY_SOURCE_NAME = "defaultProperties";
4244

4345
@Override
4446
public void postProcessEnvironment(ConfigurableEnvironment environment,
45-
SpringApplication application) {
46-
String uri = environment.getProperty("function.uri");
47-
if (StringUtils.hasText(uri)) {
48-
Map<String, Object> map = new HashMap<String, Object>();
49-
Matcher m = uriPattern.matcher(uri);
50-
boolean matches = m.matches();
51-
52-
String jarLocation = matches ? m.group(1) : uri;
53-
String className = matches ? m.group(2) : null;
54-
String rest = matches ? m.group(3) : null;
55-
if (rest != null && rest.startsWith("main=")) {
56-
map.put("function.main", rest.substring("main=".length()));
47+
SpringApplication application) {
48+
49+
/*
50+
* Stub to resolve non-standard protocols.
51+
*/
52+
URLStreamHandlerFactory urlStreamHandlerFactory = protocol -> new URLStreamHandler() {
53+
@Override
54+
protected URLConnection openConnection(URL u) {
55+
return null;
5756
}
57+
};
58+
59+
URL url;
5860

59-
map.put("function.location", jarLocation);
60-
if (className != null && className.trim().length()>0) {
61-
map.put("function.bean", className);
61+
if (environment.containsProperty("function.uri")) {
62+
try {
63+
/*
64+
* Protocol defaults to file:
65+
*/
66+
url = new URL(new URL("file:dummy"), environment.getProperty("function.uri"),
67+
urlStreamHandlerFactory.createURLStreamHandler("app"));
6268
}
69+
catch (MalformedURLException e) {
70+
throw new IllegalArgumentException(String.format("'function.uri' property %s is invalid",
71+
environment.getProperty("function.uri")));
72+
}
73+
74+
Map<String, Object> map = new HashMap<>();
75+
76+
addQueryParameters(map, url.getQuery());
77+
78+
map.put("function.location",
79+
String.join(":", url.getProtocol(), url.getPath()));
80+
6381
addOrReplace(environment.getPropertySources(), map);
6482
}
6583
}
6684

85+
private void addQueryParameters(Map<String, Object> map, String query) {
86+
87+
if (StringUtils.hasText(query)) {
88+
89+
Map<String, String> params = new HashMap<>();
90+
Stream.of(query.split("&"))
91+
.forEach(s -> {
92+
String[] pair = s.split("=");
93+
if (pair.length == 2) {
94+
params.put(pair[0], pair[1]);
95+
}
96+
});
97+
if (params.containsKey("main")) {
98+
map.put("function.main", params.get("main"));
99+
}
100+
101+
if (params.containsKey("handler")) {
102+
map.put("function.bean", params.get("handler"));
103+
}
104+
}
105+
}
106+
67107
private void addOrReplace(MutablePropertySources propertySources,
68-
Map<String, Object> map) {
108+
Map<String, Object> map) {
69109
MapPropertySource target = null;
70110
if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
71111
PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);

src/test/java/io/projectriff/invoker/FunctionEnvironmentPostProcessorTests.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 the original author or authors.
2+
* Copyright 2016-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
1515
*/
1616
package io.projectriff.invoker;
1717

18+
import org.junit.Rule;
1819
import org.junit.Test;
20+
import org.junit.rules.ExpectedException;
1921

2022
import org.springframework.boot.test.util.TestPropertyValues;
2123
import org.springframework.core.env.StandardEnvironment;
@@ -24,6 +26,7 @@
2426

2527
/**
2628
* @author Dave Syer
29+
* @author David Turanski
2730
*
2831
*/
2932
public class FunctionEnvironmentPostProcessorTests {
@@ -32,6 +35,9 @@ public class FunctionEnvironmentPostProcessorTests {
3235

3336
private StandardEnvironment environment = new StandardEnvironment();
3437

38+
@Rule
39+
public ExpectedException expectedException = ExpectedException.none();
40+
3541
@Test
3642
public void uriWithHandler() {
3743
TestPropertyValues.of("function.uri=file:target/test-classes?handler=foo")
@@ -54,6 +60,18 @@ public void uriWithHandlerAndMain() {
5460
assertThat(environment.getProperty("function.main")).isEqualTo("FooFuncs");
5561
}
5662

63+
@Test
64+
public void uriWithMainOnly() {
65+
TestPropertyValues
66+
.of("function.uri=file:target/test-classes?main=FooFuncs")
67+
.applyTo(environment);
68+
processor.postProcessEnvironment(environment, null);
69+
assertThat(environment.getProperty("function.location"))
70+
.isEqualTo("file:target/test-classes");
71+
assertThat(environment.getProperty("function.bean")).isNull();
72+
assertThat(environment.getProperty("function.main")).isEqualTo("FooFuncs");
73+
}
74+
5775
@Test
5876
public void uriWithNoHandler() {
5977
TestPropertyValues.of("function.uri=file:target/test-classes")
@@ -70,8 +88,40 @@ public void uriWithNoEmptyHandler() {
7088
.applyTo(environment);
7189
processor.postProcessEnvironment(environment, null);
7290
assertThat(environment.getProperty("function.location"))
73-
.isEqualTo("file:target/test-classes?handler=");
91+
.isEqualTo("file:target/test-classes");
92+
assertThat(environment.getProperty("function.bean")).isNull();
93+
}
94+
95+
@Test
96+
public void uriWithNoProtocol() {
97+
TestPropertyValues.of("function.uri=target/test-classes")
98+
.applyTo(environment);
99+
processor.postProcessEnvironment(environment, null);
100+
assertThat(environment.getProperty("function.location"))
101+
.isEqualTo("file:target/test-classes");
102+
}
103+
104+
@Test
105+
public void uriWithAppProtocol() {
106+
TestPropertyValues.of("function.uri=app:classpath?handler=io.projectriff.functions.Doubler")
107+
.applyTo(environment);
108+
processor.postProcessEnvironment(environment, null);
109+
assertThat(environment.getProperty("function.location"))
110+
.isEqualTo("app:classpath");
111+
assertThat(environment.getProperty("function.bean"))
112+
.isEqualTo("io.projectriff.functions.Doubler");
113+
}
114+
115+
@Test
116+
public void invalidUrl() {
117+
TestPropertyValues
118+
.of("function.uri=file:target/test-classes&handler=foo&main=FooFuncs")
119+
.applyTo(environment);
120+
processor.postProcessEnvironment(environment, null);
121+
assertThat(environment.getProperty("function.location"))
122+
.isEqualTo("file:target/test-classes&handler=foo&main=FooFuncs");
74123
assertThat(environment.getProperty("function.bean")).isNull();
124+
assertThat(environment.getProperty("function.main")).isNull();
75125
}
76126

77127
}

0 commit comments

Comments
 (0)