Skip to content

Commit 8c864ae

Browse files
SentryManrbygrave
andauthored
[http-client] Add @Headers Annotation (#402)
* add Headers Annotation * Format only changes --------- Co-authored-by: Rob Bygrave <[email protected]>
1 parent 755b491 commit 8c864ae

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.avaje.http.api;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.ElementType.TYPE;
5+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
6+
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* Headers for an Http <code>@Client</code> interface method.
12+
*
13+
* <p>We can put this on a method or the interface to add preset headers to the generated
14+
* implementation bean property.
15+
*
16+
* <pre>{@code
17+
* @Headers({
18+
* "Accept: application/vnd.github.v3.full+json",
19+
* "User-Agent: Avaje-Sample-App"
20+
* })
21+
* @Get("users/{username}")
22+
* User getUser(@Path("username") String username);
23+
*
24+
* }</pre>
25+
*/
26+
@Retention(RUNTIME)
27+
@Target({TYPE, METHOD})
28+
public @interface Headers {
29+
30+
/** The array of headers */
31+
String[] value();
32+
}

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientMethodWriter.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@
77
import javax.lang.model.util.ElementFilter;
88
import java.util.List;
99
import java.util.Map;
10+
import java.util.Map.Entry;
1011
import java.util.Optional;
1112
import java.util.Set;
13+
import java.util.function.Function;
1214
import java.util.stream.Collectors;
15+
import java.util.stream.Stream;
1316

1417
import static io.avaje.http.generator.core.ProcessingContext.*;
18+
import static java.util.stream.Collectors.toList;
1519
import static java.util.stream.Collectors.toMap;
1620

1721
/**
@@ -35,6 +39,7 @@ final class ClientMethodWriter {
3539
private final boolean useConfig;
3640
private final Map<String, String> segmentPropertyMap;
3741
private final Set<String> propertyConstants;
42+
private final List<Entry<String, String>> presetHeaders;
3843

3944
ClientMethodWriter(MethodReader method, Append writer, boolean useJsonb, Set<String> propertyConstants) {
4045
this.method = method;
@@ -50,6 +55,24 @@ final class ClientMethodWriter {
5055
.filter(Segment::isProperty)
5156
.collect(toMap(Segment::name, s -> Util.sanitizeName(s.name()).toUpperCase()));
5257
this.propertyConstants = propertyConstants;
58+
var element = method.element();
59+
60+
this.presetHeaders =
61+
Stream.concat(
62+
HeadersPrism.getOptionalOn(element).stream(),
63+
HeadersPrism.getOptionalOn(element.getEnclosingElement()).stream())
64+
.map(HeadersPrism::value)
65+
.map(List::stream)
66+
.flatMap(Function.identity())
67+
.peek(
68+
s -> {
69+
if (!s.contains(":")) {
70+
logError(element, "@Headers value must have a \":\"", method);
71+
}
72+
})
73+
.map(s -> s.split(":", 2))
74+
.filter(a -> a.length == 2)
75+
.map(a -> Map.entry(a[0].trim(), a[1].trim())).collect(toList());
5376
}
5477

5578
void addImportTypes(ControllerReader reader) {
@@ -272,6 +295,8 @@ private void writeHeaders() {
272295
}
273296
}
274297
}
298+
presetHeaders.forEach(e ->
299+
writer.append(" .header(\"%s\", \"%s\")", e.getKey(), e.getValue().replace("\\", "\\\\")).eol());
275300
}
276301

277302
private void writeBeanParams(PathSegments segments) {

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientProcessor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
import io.avaje.http.generator.core.ControllerReader;
2222
import io.avaje.http.generator.core.ImportPrism;
2323
import io.avaje.http.generator.core.ProcessingContext;
24+
import io.avaje.prism.GeneratePrism;
2425

26+
@GeneratePrism(io.avaje.http.api.Headers.class)
2527
@SupportedAnnotationTypes({ClientPrism.PRISM_TYPE, ImportPrism.PRISM_TYPE})
2628
public class ClientProcessor extends AbstractProcessor {
2729

http-generator-client/src/test/java/io/avaje/http/generator/client/clients/TitanFall.java

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

33
import io.avaje.http.api.Client;
44
import io.avaje.http.api.Get;
5+
import io.avaje.http.api.Headers;
56

67
@Client
8+
@Headers("Content-Type: applicaton/json")
79
public interface TitanFall {
810

911
@Get("/${titan}/${drop.point}")
12+
@Headers("Something: \\invalid\n\t")
1013
Titan titanFall();
1114

1215

1316
@Get("/${titan}/copium")
17+
@Headers(" Accept : applicaton/json")
1418
Titan titanFall3();
1519
}

0 commit comments

Comments
 (0)