Skip to content

Commit 27b371d

Browse files
committed
#39 - Allow path params to use "normal" { } as well as : for Javalin
1 parent 555fe8c commit 27b371d

File tree

7 files changed

+88
-66
lines changed

7 files changed

+88
-66
lines changed

http-generator-core/src/main/java/io/avaje/http/generator/core/PathSegments.java

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,39 +10,40 @@
1010

1111
public class PathSegments {
1212

13-
static final PathSegments EMPTY = new PathSegments("", Collections.emptySet());
13+
static final PathSegments EMPTY = new PathSegments(new Chunks(), Collections.emptySet());
1414

1515
static PathSegments parse(String fullPath) {
1616

1717
Set<Segment> segments = new LinkedHashSet<>();
1818

19-
StringBuilder path = new StringBuilder();
20-
19+
Chunks chunks = new Chunks();
2120
if ("/".equals(fullPath)) {
22-
path.append("/");
21+
chunks.literal("/");
2322

2423
} else {
2524
for (String section : fullPath.split("/")) {
2625
if (!section.isEmpty()) {
27-
path.append("/");
26+
chunks.literal("/");
2827
if (section.startsWith(":")) {
29-
Segment segment = createSegment(section.substring(1));
28+
final String name = section.substring(1);
29+
Segment segment = createSegment(name);
3030
segments.add(segment);
31-
path.append(segment.path(section, ":", ""));
31+
chunks.named(segment.path(name));
3232

3333
} else if ((section.startsWith("{") && (section.endsWith("}")))) {
34-
Segment segment = createSegment(section.substring(1, section.length() - 1));
34+
String name = section.substring(1, section.length() - 1);
35+
Segment segment = createSegment(name);
3536
segments.add(segment);
36-
path.append(segment.path(section, "{", "}"));
37+
chunks.named(segment.path(name));
3738

3839
} else {
39-
path.append(section);
40+
chunks.literal(section);
4041
}
4142
}
4243
}
4344
}
4445

45-
return new PathSegments(path.toString(), segments);
46+
return new PathSegments(chunks, segments);
4647
}
4748

4849
private static Segment createSegment(String val) {
@@ -54,16 +55,16 @@ private static Segment createSegment(String val) {
5455
return new Segment(matrixSplit[0], matrixKeys);
5556
}
5657

57-
private final String fullPath;
58+
private final Chunks chunks;
5859

5960
private final Set<Segment> segments;
6061

6162
private final List<Segment> withMatrixs = new ArrayList<>();
6263

6364
private final Set<String> allNames = new HashSet<>();
6465

65-
private PathSegments(String fullPath, Set<Segment> segments) {
66-
this.fullPath = fullPath;
66+
private PathSegments(Chunks chunks, Set<Segment> segments) {
67+
this.chunks = chunks;
6768
this.segments = segments;
6869
for (Segment segment : segments) {
6970
segment.addNames(allNames);
@@ -92,8 +93,22 @@ public Segment segment(String varName) {
9293
return null;
9394
}
9495

96+
/**
97+
* Return full path with <code>{}</code for named path params.
98+
*/
9599
public String fullPath() {
96-
return fullPath;
100+
return fullPath("{", "}");
101+
}
102+
103+
/**
104+
* Return full path with colon for named path params (Javalin).
105+
*/
106+
public String fullPathColon() {
107+
return fullPath(":", "");
108+
}
109+
110+
private String fullPath(String prefix, String suffix) {
111+
return chunks.fullPath(prefix, suffix);
97112
}
98113

99114
public static class Segment {
@@ -184,11 +199,54 @@ boolean isRequired(String varName) {
184199
return name.equals(varName);
185200
}
186201

187-
String path(String section, String prefix, String suffix) {
202+
String path(String section) {
188203
if (!hasMatrixParams()) {
189204
return section;
190205
}
191-
return prefix + name + "_segment" + suffix;
206+
return name + "_segment";
192207
}
193208
}
209+
210+
private static class Chunks {
211+
private final List<Chunk> chunks = new ArrayList<>();
212+
213+
void named(String name) {
214+
chunks.add(new Chunk(name));
215+
}
216+
217+
void literal(String val) {
218+
chunks.add(new LiteralChunk(val));
219+
}
220+
221+
String fullPath(String prefix, String suffix) {
222+
StringBuilder sb = new StringBuilder();
223+
for (Chunk chunk : chunks) {
224+
chunk.append(sb, prefix, suffix);
225+
}
226+
return sb.toString();
227+
}
228+
}
229+
230+
private static class LiteralChunk extends Chunk {
231+
private LiteralChunk(String value) {
232+
super(value);
233+
}
234+
235+
@Override
236+
void append(StringBuilder fullPath, String prefix, String suffix) {
237+
fullPath.append(value);
238+
}
239+
}
240+
241+
private static class Chunk {
242+
final String value;
243+
private Chunk(String value) {
244+
this.value = value;
245+
}
246+
247+
void append(StringBuilder fullPath, String prefix, String suffix) {
248+
fullPath.append(prefix).append(value).append(suffix);
249+
}
250+
}
251+
194252
}

http-generator-core/src/main/java/io/avaje/http/generator/core/openapi/MethodDocBuilder.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void build() {
4444
operation.setDeprecated(true);
4545
}
4646

47-
PathItem pathItem = ctx.pathItem(normalisePath(methodReader.getFullPath()));
47+
PathItem pathItem = ctx.pathItem(methodReader.getFullPath());
4848
switch (methodReader.getWebMethod()) {
4949
case GET:
5050
pathItem.setGet(operation);
@@ -85,10 +85,6 @@ public void build() {
8585
responses.addApiResponse(methodReader.getStatusCode(), response);
8686
}
8787

88-
String normalisePath(String fullPath) {
89-
return fullPath.replaceAll("(:)([^/]+)", "{$2}");
90-
}
91-
9288
DocContext getContext() {
9389
return ctx;
9490
}

http-generator-core/src/test/java/io/avaje/http/generator/core/PathSegmentsTest.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public void parse_snake() {
5353
assertTrue(segments.contains("one-a"));
5454
assertTrue(segments.contains("two-b"));
5555

56-
assertEquals("/fo/:one-a/:two-b", segments.fullPath());
57-
56+
assertEquals("/fo/:one-a/:two-b", segments.fullPathColon());
57+
assertEquals("/fo/{one-a}/{two-b}", segments.fullPath());
5858
}
5959

6060
@Test
@@ -63,7 +63,6 @@ public void parse_empty() {
6363
PathSegments segments = PathSegments.parse("/hello");
6464
assertFalse(segments.contains("hello"));
6565
assertEquals("/hello", segments.fullPath());
66-
6766
}
6867

6968
@Test
@@ -80,7 +79,8 @@ public void pathMatrixParams_colonPrefix() {
8079
assertThat(matrixSegments.get(1).name()).isEqualTo("foo");
8180
assertThat(matrixSegments.get(1).matrixKeys()).containsOnly("baz");
8281

83-
assertEquals("/:id_segment/:foo_segment", segments.fullPath());
82+
assertEquals("/:id_segment/:foo_segment", segments.fullPathColon());
83+
assertEquals("/{id_segment}/{foo_segment}", segments.fullPath());
8484
}
8585

8686
@Test
@@ -98,17 +98,20 @@ public void pathMatrixParams_normalised() {
9898
assertThat(matrixSegments.get(1).matrixKeys()).containsOnly("baz");
9999

100100
assertEquals("/{id_segment}/{foo_segment}", segments.fullPath());
101+
assertEquals("/:id_segment/:foo_segment", segments.fullPathColon());
101102
}
102103

103104
@Test
104105
public void pathMatrixParams_fullPath() {
105106

106107
PathSegments segments = PathSegments.parse("/start/:id;key;other/:foo;baz/end");
107-
assertEquals("/start/:id_segment/:foo_segment/end", segments.fullPath());
108+
assertEquals("/start/:id_segment/:foo_segment/end", segments.fullPathColon());
109+
assertEquals("/start/{id_segment}/{foo_segment}/end", segments.fullPath());
108110

109111
segments = PathSegments.parse("/start/:id;key;other/middle/:foo;baz/end");
110112

111-
assertEquals("/start/:id_segment/middle/:foo_segment/end", segments.fullPath());
113+
assertEquals("/start/:id_segment/middle/:foo_segment/end", segments.fullPathColon());
114+
assertEquals("/start/{id_segment}/middle/{foo_segment}/end", segments.fullPath());
112115
}
113116

114117
@Test

http-generator-core/src/test/java/io/avaje/http/generator/core/openapi/MethodDocBuilderTest.java

Lines changed: 0 additions & 35 deletions
This file was deleted.

http-generator-javalin/src/main/java/io/avaje/http/generator/javalin/ControllerMethodWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ControllerMethodWriter {
3131
void write(boolean requestScoped) {
3232

3333
final PathSegments segments = method.getPathSegments();
34-
final String fullPath = segments.fullPath();
34+
final String fullPath = segments.fullPathColon();
3535

3636
writer.append(" ApiBuilder.%s(\"%s\", ctx -> {", webMethod.name().toLowerCase(), fullPath).eol();
3737
writer.append(" ctx.status(%s);", method.getStatusCode()).eol();

tests/test-helidon/src/main/java/org/example/FooController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public Foo putIt(FooBody payload) {
6060
return foo;
6161
}
6262

63-
@Delete("{id}")
63+
@Delete(":id")
6464
public Foo deleteIt(long id, FooBody body) {
6565
Foo foo = new Foo();
6666
foo.name = body.name + "=" + body.getMessage() + " - Delete " + id;

tests/test-javalin/src/main/java/org/example/myapp/web/BazController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class BazController extends BaseController<Baz, Long> {
2222
*
2323
* @return The list of baz
2424
*/
25-
@Get("findbyname/:name")
25+
@Get("findbyname/{name}")
2626
List<Baz> searchByName(String name) {
2727

2828
Baz b1 = new Baz();

0 commit comments

Comments
 (0)