Skip to content

Commit f3fd134

Browse files
authored
Add BodyString annotation, to support controllers with body of type String (#198)
* Body String * professionals have standards * fix bodyPublisher * rename to body * import * Update Body.java * Revert "rename to body" * fix other body types * input stream body * Update BodyString.java * Update ElementReader.java * now will use application/text fo string
1 parent 3899cfb commit f3fd134

File tree

10 files changed

+71
-23
lines changed

10 files changed

+71
-23
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.avaje.http.api;
2+
3+
import static java.lang.annotation.ElementType.PARAMETER;
4+
import static java.lang.annotation.RetentionPolicy.SOURCE;
5+
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.Target;
8+
9+
/**
10+
* Marks a controller string method parameter to be a string body. Use when you expect to receive an
11+
* application/text or similar body request.
12+
*/
13+
@Retention(SOURCE)
14+
@Target(PARAMETER)
15+
public @interface BodyString {}

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

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public class ElementReader {
3838
private boolean isParamCollection;
3939
private boolean isParamMap;
4040
private final Set<String> imports = new HashSet<>();
41-
// private boolean notNullJavax;
4241

4342
ElementReader(Element element, ParamType defaultType, boolean formMarker) {
4443
this(element, null, Util.typeDef(element.asType()), defaultType, formMarker);
@@ -140,13 +139,11 @@ private void readAnnotations(Element element, ParamType defaultType) {
140139
if (defaultVal != null) {
141140
this.paramDefault = defaultVal.value();
142141
}
143-
final var form = FormPrism.getInstanceOn(element);
144-
if (form != null) {
142+
if (FormPrism.isPresent(element)) {
145143
this.paramType = ParamType.FORM;
146144
return;
147145
}
148-
final var beanParam = BeanParamPrism.getInstanceOn(element);
149-
if (beanParam != null) {
146+
if (BeanParamPrism.isPresent(element)) {
150147
this.paramType = ParamType.BEANPARAM;
151148
return;
152149
}
@@ -185,6 +182,12 @@ private void readAnnotations(Element element, ParamType defaultType) {
185182
return;
186183
}
187184

185+
if ("java.lang.String".equals(element.asType().toString())
186+
&& BodyStringPrism.isPresent(element)) {
187+
this.paramType = ParamType.BODY;
188+
return;
189+
}
190+
188191
if (paramType == null) {
189192
this.impliedParamType = true;
190193
if (typeHandler != null) {
@@ -249,22 +252,14 @@ void writeParamName(Append writer) {
249252
* Build the OpenAPI documentation for this parameter.
250253
*/
251254
void buildApiDocumentation(MethodDocBuilder methodDoc) {
252-
if (!isPlatformContext() && !isParamMap && paramType != ParamType.BEANPARAM) {
253-
if (includeParam()) {
254-
new MethodParamDocBuilder(methodDoc, this).build();
255-
}
255+
if (!isPlatformContext()
256+
&& !isParamMap
257+
&& paramType != ParamType.BEANPARAM
258+
&& !IgnorePrism.isPresent(element)) {
259+
new MethodParamDocBuilder(methodDoc, this).build();
256260
}
257261
}
258262

259-
private boolean includeParam() {
260-
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
261-
if ("io.avaje.http.api.Ignore".equals(annotationMirror.getAnnotationType().toString())) {
262-
return false;
263-
}
264-
}
265-
return true;
266-
}
267-
268263
void writeValidate(Append writer) {
269264
if (!contextType && typeHandler == null) {
270265
if (useValidation) {
@@ -338,7 +333,7 @@ private boolean setValue(Append writer, PathSegments segments, String shortType)
338333
writer.append(asMethod);
339334
}
340335

341-
if (typeHandler == null) {
336+
if (typeHandler == null || paramType == ParamType.BODY) {
342337
// this is a body (POST, PATCH)
343338
writer.append(platform().bodyAsClass(type));
344339

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class SchemaDocBuilder {
4545

4646
private static final String APP_FORM = "application/x-www-form-urlencoded";
4747
private static final String APP_JSON = "application/json";
48+
private static final String APP_TXT = "application/text";
4849

4950
private final Elements elements;
5051
private final Types types;
@@ -113,6 +114,9 @@ void addRequestBody(Operation operation, Schema schema, boolean asForm, String d
113114
mt.schema(schema);
114115

115116
String mime = asForm ? APP_FORM : APP_JSON;
117+
if (schema instanceof StringSchema) {
118+
mime = APP_TXT;
119+
}
116120
body.getContent().addMediaType(mime, mt);
117121
}
118122

http-generator-core/src/main/java/io/avaje/http/generator/core/package-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@GeneratePrism(value = io.avaje.http.api.QueryParam.class, publicAccess = true)
66
@GeneratePrism(value = io.avaje.http.api.Client.class, publicAccess = true)
77
@GeneratePrism(value = io.avaje.http.api.Cookie.class, publicAccess = true)
8+
@GeneratePrism(value = io.avaje.http.api.BodyString.class, publicAccess = true)
89
@GeneratePrism(value = io.avaje.http.api.Default.class, publicAccess = true)
910
@GeneratePrism(value = io.avaje.http.api.Delete.class, publicAccess = true)
1011
@GeneratePrism(value = io.avaje.http.api.Form.class, publicAccess = true)

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package io.avaje.http.generator.javalin;
22

3-
import io.avaje.http.generator.core.*;
4-
53
import java.util.List;
64

5+
import io.avaje.http.generator.core.Append;
6+
import io.avaje.http.generator.core.ControllerReader;
7+
import io.avaje.http.generator.core.ParamType;
8+
import io.avaje.http.generator.core.PlatformAdapter;
9+
import io.avaje.http.generator.core.UType;
10+
711
class JavalinAdapter implements PlatformAdapter {
812

913
static final String JAVALIN3_CONTEXT = "io.javalin.http.Context";
@@ -31,9 +35,11 @@ public boolean isBodyMethodParam() {
3135

3236
@Override
3337
public String bodyAsClass(UType type) {
34-
if (type.full().startsWith("java.io.InputStream")) {
38+
if ("java.io.InputStream".equals(type.full())) {
3539
return "ctx.bodyInputStream()";
36-
} else if (type.full().startsWith("byte[]")) {
40+
} else if ("java.lang.String".equals(type.full())) {
41+
return "ctx.body()";
42+
} else if ("byte[]".equals(type.full())) {
3743
return "ctx.bodyAsBytes()";
3844
} else {
3945
if (useJsonB) {

http-generator-jex/src/main/java/io/avaje/http/generator/jex/JexAdapter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public boolean isBodyMethodParam() {
2929

3030
@Override
3131
public String bodyAsClass(UType uType) {
32+
if ("java.lang.String".equals(uType.full())) {
33+
return "ctx.body()";
34+
}
3235
return "ctx.bodyAsClass(" + uType.mainType() + ".class)";
3336
}
3437

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Map;
55
import java.util.Set;
66

7+
import io.avaje.http.api.BodyString;
78
import io.avaje.http.api.Controller;
89
import io.avaje.http.api.Cookie;
910
import io.avaje.http.api.Default;
@@ -40,4 +41,9 @@ String enumQueryImplied(String s, @QueryParam ServerType type) {
4041
String mapTest(Map<String, List<String>> strings, @Cookie Map<String, List<String>> cookie) {
4142
return strings.toString();
4243
}
44+
45+
@Post("/strBody")
46+
String strBody(@BodyString String body) {
47+
return body;
48+
}
4349
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.example.myapp.web.ServerType;
88

9+
import io.avaje.http.api.BodyString;
910
import io.avaje.http.api.Controller;
1011
import io.avaje.http.api.Default;
1112
import io.avaje.http.api.Form;
@@ -54,4 +55,9 @@ String stream(InputStream stream) {
5455
String bytes(byte[] array) {
5556
return array.toString();
5657
}
58+
59+
@Post("/strBody")
60+
String strBody(@BodyString String body) {
61+
return body;
62+
}
5763
}

tests/test-jex/src/main/java/org/example/web/TestController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import java.util.Set;
44

5+
import io.avaje.http.api.BodyString;
56
import io.avaje.http.api.Controller;
67
import io.avaje.http.api.Default;
78
import io.avaje.http.api.Get;
89
import io.avaje.http.api.Path;
910
import io.avaje.http.api.Post;
1011
import io.avaje.http.api.QueryParam;
12+
import io.avaje.jex.Context;
1113

1214
@Path("test/")
1315
@Controller
@@ -33,4 +35,8 @@ String enumQueryImplied(String s, @QueryParam ServerType type) {
3335
return type.name();
3436
}
3537

38+
@Post("/strBody")
39+
String strBody(@BodyString String body, Context ctx) {
40+
return body;
41+
}
3642
}

tests/test-nima-jsonb/src/main/java/org/example/TestController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.List;
55
import java.util.Set;
66

7+
import io.avaje.http.api.BodyString;
78
import io.avaje.http.api.Controller;
89
import io.avaje.http.api.Default;
910
import io.avaje.http.api.Form;
@@ -57,4 +58,9 @@ String enumQueryImplied(String s, @QueryParam ServerType type) {
5758
String stream(InputStream stream) {
5859
return stream.toString();
5960
}
61+
62+
@Post("/strBody")
63+
String strBody(@BodyString String body) {
64+
return body;
65+
}
6066
}

0 commit comments

Comments
 (0)