Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions http-api/src/main/java/io/avaje/http/api/Headers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.avaje.http.api;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Headers for an Http <code>@Client</code> interface method.
*
* <p>We can put this on a method or the interface to add preset headers to the generated
* implementation bean property.
*
* <pre>{@code
* @Headers({
* "Accept: application/vnd.github.v3.full+json",
* "User-Agent: Avaje-Sample-App"
* })
* @Get("users/{username}")
* User getUser(@Path("username") String username);
*
* }</pre>
*/
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Headers {

/** The array of headers */
String[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
import javax.lang.model.util.ElementFilter;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.avaje.http.generator.core.ProcessingContext.*;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

/**
Expand All @@ -35,6 +39,7 @@ final class ClientMethodWriter {
private final boolean useConfig;
private final Map<String, String> segmentPropertyMap;
private final Set<String> propertyConstants;
private final List<Entry<String, String>> presetHeaders;

ClientMethodWriter(MethodReader method, Append writer, boolean useJsonb, Set<String> propertyConstants) {
this.method = method;
Expand All @@ -50,6 +55,24 @@ final class ClientMethodWriter {
.filter(Segment::isProperty)
.collect(toMap(Segment::name, s -> Util.sanitizeName(s.name()).toUpperCase()));
this.propertyConstants = propertyConstants;
var element = method.element();

this.presetHeaders =
Stream.concat(
HeadersPrism.getOptionalOn(element).stream(),
HeadersPrism.getOptionalOn(element.getEnclosingElement()).stream())
.map(HeadersPrism::value)
.map(List::stream)
.flatMap(Function.identity())
.peek(
s -> {
if (!s.contains(":")) {
logError(element, "@Headers value must have a \":\"", method);
}
})
.map(s -> s.split(":", 2))
.filter(a -> a.length == 2)
.map(a -> Map.entry(a[0].trim(), a[1].trim())).collect(toList());
}

void addImportTypes(ControllerReader reader) {
Expand Down Expand Up @@ -272,6 +295,8 @@ private void writeHeaders() {
}
}
}
presetHeaders.forEach(e ->
writer.append(" .header(\"%s\", \"%s\")", e.getKey(), e.getValue().replace("\\", "\\\\")).eol());
}

private void writeBeanParams(PathSegments segments) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import io.avaje.http.generator.core.ControllerReader;
import io.avaje.http.generator.core.ImportPrism;
import io.avaje.http.generator.core.ProcessingContext;
import io.avaje.prism.GeneratePrism;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

import io.avaje.http.api.Client;
import io.avaje.http.api.Get;
import io.avaje.http.api.Headers;

@Client
@Headers("Content-Type: applicaton/json")
public interface TitanFall {

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


@Get("/${titan}/copium")
@Headers(" Accept : applicaton/json")
Titan titanFall3();
}