Skip to content

Commit

Permalink
[undertow] add functions to apply to every marked params in the runti…
Browse files Browse the repository at this point in the history
…me (#255)

## Before this PR

It is not possible to do any actions on marked params.

## After this PR

The runtime include functions that will be called on every marked params. This allow the possibility to to add safe logging among others.
  • Loading branch information
Ruben Fiszel authored and bulldozer-bot[bot] committed Apr 9, 2019
1 parent 3ba56b4 commit b5fef18
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,17 +289,19 @@ private CodeBlock endpointInvocation(EndpointDefinition endpointDefinition, List

// body parameter
getBodyParamTypeArgument(endpointDefinition.getArgs()).ifPresent(bodyParam -> {
String paramName = bodyParam.getArgName().get();
if (bodyParam.getType().accept(TypeVisitor.IS_BINARY)) {
// TODO(ckozak): Support aliased and optional binary types
code.addStatement("$1T $2N = $3N.bodySerDe().deserializeInputStream($4N)",
InputStream.class, bodyParam.getArgName().get(), RUNTIME_VAR_NAME, EXCHANGE_VAR_NAME);
InputStream.class, paramName, RUNTIME_VAR_NAME, EXCHANGE_VAR_NAME);
} else {
code.addStatement("$1T $2N = $3N.deserialize($4N)",
typeMapper.getClassName(bodyParam.getType()).box(),
bodyParam.getArgName().get(),
paramName,
DESERIALIZER_VAR_NAME,
EXCHANGE_VAR_NAME);
}
code.add(generateParamMarkers(bodyParam.getMarkers(), paramName, typeMapper));
});

// path parameters
Expand Down Expand Up @@ -368,6 +370,19 @@ private CodeBlock endpointInvocation(EndpointDefinition endpointDefinition, List
return code.build();
}

private CodeBlock generateParamMarkers(
List<Type> markers,
String paramName,
TypeMapper typeMapper) {
return CodeBlocks.of(markers.stream().map(marker ->
CodeBlock.of("$1N.markers().param($2S, $3S, $4N, $5N);",
RUNTIME_VAR_NAME,
typeMapper.getClassName(marker).box(), paramName,
paramName,
EXCHANGE_VAR_NAME))
.collect(Collectors.toList()));
}

// Adds code for authorization. Returns an optional that contains the name of the variable that contains the
// deserialized optional parameter.
private Optional<String> addAuthCode(
Expand Down Expand Up @@ -504,27 +519,32 @@ private CodeBlock generateParameterCodeBlock(Stream<ArgumentDefinition> params,
arg -> {
Type normalizedType = UndertowTypeFunctions.toConjureTypeWithoutAliases(arg.getType(),
typeDefinitions);
String paramName = arg.getArgName().get();
final CodeBlock retrieveParam;
if (normalizedType.equals(arg.getType())) {
// type does not contain any aliases
return decodePlainParameterCodeBlock(normalizedType, typeMapper, arg.getArgName().get(),
retrieveParam = decodePlainParameterCodeBlock(normalizedType, typeMapper, paramName,
paramsVarName,
toParamId.apply(arg));
} else {
// type contains aliases: decode raw value and then construct real value from raw one
String rawVarName = arg.getArgName().get() + "Raw";
return CodeBlocks.of(
retrieveParam = CodeBlocks.of(
decodePlainParameterCodeBlock(normalizedType, typeMapper, rawVarName,
paramsVarName,
toParamId.apply(arg)),
CodeBlocks.statement(
"$1T $2N = $3L",
typeMapper.getClassName(arg.getType()),
arg.getArgName().get(),
paramName,
createConstructorForTypeWithReference(arg.getType(), rawVarName,
typeDefinitions, typeMapper)
)
);
}
return CodeBlocks.of(
retrieveParam,
generateParamMarkers(arg.getMarkers(), paramName, typeMapper));
}).collect(Collectors.toList()));
}

Expand Down
9 changes: 9 additions & 0 deletions conjure-java-core/src/test/resources/example-service.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ services:
param-id: Test-Header
param-type: header
type: string
markers:
- Safe
returns: Dataset

getDataset:
Expand Down Expand Up @@ -104,6 +106,7 @@ services:
type: rid
markers:
- Safe
- Nonnull
returns: optional<binary>

getAliasedString:
Expand All @@ -121,6 +124,8 @@ services:
input:
type: binary
param-type: body
markers:
- Safe

uploadAliasedRawData:
http: POST /datasets/upload-raw-aliased
Expand Down Expand Up @@ -170,6 +175,8 @@ services:
type: rid
param-id: datasetRid
param-type: path
markers:
- Safe
returns: optional<string>

testQueryParams:
Expand All @@ -180,6 +187,8 @@ services:
type: rid
param-id: different
param-type: query
markers:
- Safe
optionalMiddle:
type: optional<rid>
param-type: query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.Set;
import javax.annotation.Generated;
import javax.annotation.Nonnull;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
Expand Down Expand Up @@ -44,7 +45,7 @@ public interface TestService {
@Path("catalog/datasets")
Dataset createDataset(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@HeaderParam("Test-Header") String testHeaderArg,
@HeaderParam("Test-Header") @Safe String testHeaderArg,
@NotNull CreateDatasetRequest request);

@GET
Expand Down Expand Up @@ -72,7 +73,7 @@ public interface TestService {
@Produces(MediaType.APPLICATION_OCTET_STREAM)
Optional<StreamingOutput> maybeGetRawData(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@PathParam("datasetRid") @Safe ResourceIdentifier datasetRid);
@PathParam("datasetRid") @Safe @Nonnull ResourceIdentifier datasetRid);

@GET
@Path("catalog/datasets/{datasetRid}/string-aliased")
Expand All @@ -85,7 +86,7 @@ public interface TestService {
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
void uploadRawData(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@NotNull InputStream input);
@NotNull @Safe InputStream input);

@POST
@Path("catalog/datasets/upload-raw-aliased")
Expand Down Expand Up @@ -122,13 +123,13 @@ public interface TestService {
@Path("catalog/datasets/{datasetRid}/testParam")
Optional<String> testParam(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@PathParam("datasetRid") ResourceIdentifier datasetRid);
@PathParam("datasetRid") @Safe ResourceIdentifier datasetRid);

@POST
@Path("catalog/test-query-params")
int testQueryParams(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@QueryParam("different") ResourceIdentifier something,
@QueryParam("different") @Safe ResourceIdentifier something,
@QueryParam("implicit") ResourceIdentifier implicit,
@QueryParam("optionalMiddle") Optional<ResourceIdentifier> optionalMiddle,
@QueryParam("setEnd") Set<String> setEnd,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.Set;
import javax.annotation.Generated;
import javax.annotation.Nonnull;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
Expand Down Expand Up @@ -44,7 +45,7 @@ public interface TestService {
@Path("catalog/datasets")
Dataset createDataset(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@HeaderParam("Test-Header") String testHeaderArg,
@HeaderParam("Test-Header") @Safe String testHeaderArg,
@NotNull CreateDatasetRequest request);

@GET
Expand Down Expand Up @@ -72,7 +73,7 @@ public interface TestService {
@Produces(MediaType.APPLICATION_OCTET_STREAM)
Optional<StreamingOutput> maybeGetRawData(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@PathParam("datasetRid") @Safe ResourceIdentifier datasetRid);
@PathParam("datasetRid") @Safe @Nonnull ResourceIdentifier datasetRid);

@GET
@Path("catalog/datasets/{datasetRid}/string-aliased")
Expand All @@ -85,7 +86,7 @@ public interface TestService {
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
void uploadRawData(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@NotNull InputStream input);
@NotNull @Safe InputStream input);

@POST
@Path("catalog/datasets/upload-raw-aliased")
Expand Down Expand Up @@ -122,13 +123,13 @@ public interface TestService {
@Path("catalog/datasets/{datasetRid}/testParam")
Optional<String> testParam(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@PathParam("datasetRid") ResourceIdentifier datasetRid);
@PathParam("datasetRid") @Safe ResourceIdentifier datasetRid);

@POST
@Path("catalog/test-query-params")
int testQueryParams(
@HeaderParam("Authorization") @NotNull AuthHeader authHeader,
@QueryParam("different") ResourceIdentifier something,
@QueryParam("different") @Safe ResourceIdentifier something,
@QueryParam("implicit") ResourceIdentifier implicit,
@QueryParam("optionalMiddle") Optional<ResourceIdentifier> optionalMiddle,
@QueryParam("setEnd") Set<String> setEnd,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public final class TestServiceEndpoints implements UndertowService {
HeaderMap headerParams = exchange.getRequestHeaders();
String testHeaderArg =
runtime.plainSerDe().deserializeString(headerParams.get("Test-Header"));
runtime.markers()
.param("com.palantir.redaction.Safe", "testHeaderArg", testHeaderArg, exchange);
Dataset result = delegate.createDataset(authHeader, testHeaderArg, request);
serializer.serialize(result, exchange);
}
Expand Down Expand Up @@ -195,6 +197,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
Optional<Dataset> result = delegate.getDataset(authHeader, datasetRid);
if (result.isPresent()) {
serializer.serialize(result, exchange);
Expand Down Expand Up @@ -246,6 +250,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
BinaryResponseBody result = delegate.getRawData(authHeader, datasetRid);
runtime.bodySerDe().serialize(result, exchange);
}
Expand Down Expand Up @@ -297,6 +303,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
NestedAliasedBinary result = delegate.getAliasedRawData(authHeader, datasetRid);
serializer.serialize(result, exchange);
}
Expand Down Expand Up @@ -344,6 +352,9 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
runtime.markers().param("javax.annotation.Nonnull", "datasetRid", datasetRid, exchange);
Optional<BinaryResponseBody> result = delegate.maybeGetRawData(authHeader, datasetRid);
if (result.isPresent()) {
runtime.bodySerDe().serialize(result.get(), exchange);
Expand Down Expand Up @@ -398,6 +409,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
AliasedString result = delegate.getAliasedString(authHeader, datasetRid);
serializer.serialize(result, exchange);
}
Expand Down Expand Up @@ -442,6 +455,7 @@ public final class TestServiceEndpoints implements UndertowService {
public void handleRequest(HttpServerExchange exchange) throws IOException {
AuthHeader authHeader = runtime.auth().header(exchange);
InputStream input = runtime.bodySerDe().deserializeInputStream(exchange);
runtime.markers().param("com.palantir.redaction.Safe", "input", input, exchange);
delegate.uploadRawData(authHeader, input);
exchange.setStatusCode(StatusCodes.NO_CONTENT);
}
Expand Down Expand Up @@ -540,6 +554,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
Set<String> result = delegate.getBranches(authHeader, datasetRid);
serializer.serialize(result, exchange);
}
Expand Down Expand Up @@ -591,6 +607,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
Set<String> result = delegate.getBranchesDeprecated(authHeader, datasetRid);
serializer.serialize(result, exchange);
}
Expand Down Expand Up @@ -641,6 +659,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
String branch = runtime.plainSerDe().deserializeString(pathParams.get("branch"));
Optional<String> result = delegate.resolveBranch(authHeader, datasetRid, branch);
if (result.isPresent()) {
Expand Down Expand Up @@ -696,6 +716,8 @@ public final class TestServiceEndpoints implements UndertowService {
exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters();
ResourceIdentifier datasetRid =
runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid"));
runtime.markers()
.param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange);
Optional<String> result = delegate.testParam(authHeader, datasetRid);
if (result.isPresent()) {
serializer.serialize(result, exchange);
Expand Down Expand Up @@ -753,6 +775,8 @@ public final class TestServiceEndpoints implements UndertowService {
Map<String, Deque<String>> queryParams = exchange.getQueryParameters();
ResourceIdentifier something =
runtime.plainSerDe().deserializeRid(queryParams.get("different"));
runtime.markers()
.param("com.palantir.redaction.Safe", "something", something, exchange);
Optional<ResourceIdentifier> optionalMiddle =
runtime.plainSerDe().deserializeOptionalRid(queryParams.get("optionalMiddle"));
ResourceIdentifier implicit =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.palantir.conjure.java.undertow.lib.AuthorizationExtractor;
import com.palantir.conjure.java.undertow.lib.BodySerDe;
import com.palantir.conjure.java.undertow.lib.MarkerCallback;
import com.palantir.conjure.java.undertow.lib.PlainSerDe;
import com.palantir.conjure.java.undertow.lib.UndertowRuntime;
import com.palantir.logsafe.Preconditions;
Expand All @@ -33,11 +34,16 @@ public final class ConjureUndertowRuntime implements UndertowRuntime {

private final BodySerDe bodySerDe;
private final AuthorizationExtractor auth;
private final MarkerCallback markerCallback;

private ConjureUndertowRuntime(Builder builder) {
this.bodySerDe = new ConjureBodySerDe(builder.encodings.isEmpty()
? ImmutableList.of(Encodings.json(), Encodings.cbor()) : builder.encodings);
this.auth = new ConjureAuthorizationExtractor(plainSerDe());
List<ParamMarker> paramMarkers = ImmutableList.copyOf(builder.paramMarkers);
this.markerCallback = (markerClass, parameterName, parameterValue, exchange) ->
paramMarkers.forEach(marked -> marked.mark(markerClass, parameterName, parameterValue, exchange));

}

public static Builder builder() {
Expand All @@ -54,6 +60,12 @@ public PlainSerDe plainSerDe() {
return ConjurePlainSerDe.INSTANCE;
}


@Override
public MarkerCallback markers() {
return markerCallback;
}

@Override
public AuthorizationExtractor auth() {
return auth;
Expand All @@ -62,6 +74,7 @@ public AuthorizationExtractor auth() {
public static final class Builder {

private final List<Encoding> encodings = Lists.newArrayList();
private final List<ParamMarker> paramMarkers = Lists.newArrayList();

private Builder() {}

Expand All @@ -71,6 +84,12 @@ public Builder encodings(Encoding value) {
return this;
}

@CanIgnoreReturnValue
public Builder paramMarker(ParamMarker value) {
paramMarkers.add(Preconditions.checkNotNull(value, "Value is required"));
return this;
}

public ConjureUndertowRuntime build() {
return new ConjureUndertowRuntime(this);
}
Expand Down
Loading

0 comments on commit b5fef18

Please sign in to comment.