Skip to content

Commit

Permalink
Fix greedy label param names in OpenAPI
Browse files Browse the repository at this point in the history
Services like API Gateway that use "greedy" labels require that bath
the segment and the corresponding parameter name contain a "+". We
previously included the "+" in the URI label but not in the parameter
name.
  • Loading branch information
mtdowling committed Nov 24, 2020
1 parent a1bb42e commit 622089b
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import software.amazon.smithy.model.knowledge.HttpBinding;
import software.amazon.smithy.model.knowledge.HttpBindingIndex;
import software.amazon.smithy.model.knowledge.OperationIndex;
import software.amazon.smithy.model.pattern.SmithyPattern;
import software.amazon.smithy.model.shapes.CollectionShape;
import software.amazon.smithy.model.shapes.MemberShape;
import software.amazon.smithy.model.shapes.OperationShape;
Expand All @@ -38,6 +39,7 @@
import software.amazon.smithy.model.traits.HttpTrait;
import software.amazon.smithy.model.traits.TimestampFormatTrait;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.openapi.OpenApiException;
import software.amazon.smithy.openapi.fromsmithy.Context;
import software.amazon.smithy.openapi.fromsmithy.OpenApiProtocol;
import software.amazon.smithy.openapi.model.MediaTypeObject;
Expand Down Expand Up @@ -120,10 +122,26 @@ public Optional<Operation> createOperation(Context<T> context, OperationShape op
private List<ParameterObject> createPathParameters(Context<T> context, OperationShape operation) {
List<ParameterObject> result = new ArrayList<>();
HttpBindingIndex bindingIndex = HttpBindingIndex.of(context.getModel());
HttpTrait httpTrait = operation.expectTrait(HttpTrait.class);

for (HttpBinding binding : bindingIndex.getRequestBindings(operation, HttpBinding.Location.LABEL)) {
Schema schema = createPathParameterSchema(context, binding);
String memberName = binding.getMemberName();

SmithyPattern.Segment label = httpTrait.getUri()
.getLabel(memberName)
.orElseThrow(() -> new OpenApiException(String.format(
"Unable to find URI label on %s for %s: %s",
operation.getId(),
binding.getMemberName(),
httpTrait.getUri())));

// Greedy labels in OpenAPI need to include the label in the generated parameter.
// For example, given "/{foo+}", the parameter name must be "foo+".
String name = label.isGreedyLabel() ? label.getContent() + "+" : label.getContent();

result.add(ModelUtils.createParameterMember(context, binding.getMember())
.name(name)
.in("path")
.schema(schema)
.build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public class AwsRestJson1ProtocolTest {
"adds-header-mediatype-format.json",
"supports-payloads.json",
"aws-rest-json-uses-jsonname.json",
"synthesizes-contents.json"
"synthesizes-contents.json",
"greedy-labels.json"
})

public void testProtocolResult(String smithy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"smithy": "1.0",
"shapes": {
"smithy.example#Service": {
"type": "service",
"version": "2006-03-01",
"operations": [
{
"target": "smithy.example#Operation"
}
],
"traits": {
"aws.protocols#restJson1": {}
}
},
"smithy.example#Operation": {
"type": "operation",
"input": {
"target": "smithy.example#OperationInput"
},
"traits": {
"smithy.api#http": {
"uri": "/{foo}/{baz+}",
"method": "POST"
}
}
},
"smithy.example#OperationInput": {
"type": "structure",
"members": {
"foo": {
"target": "smithy.api#String",
"traits": {
"smithy.api#required": {},
"smithy.api#httpLabel": {}
}
},
"baz": {
"target": "smithy.api#String",
"traits": {
"smithy.api#required": {},
"smithy.api#httpLabel": {}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"openapi": "3.0.2",
"info": {
"title": "Service",
"version": "2006-03-01"
},
"paths": {
"/{foo}/{baz+}": {
"post": {
"operationId": "Operation",
"parameters": [
{
"name": "foo",
"in": "path",
"schema": {
"type": "string"
},
"required": true
},
{
"name": "baz+",
"in": "path",
"schema": {
"type": "string"
},
"required": true
}
],
"responses": {
"200": {
"description": "Operation response"
}
}
}
}
}
}

0 comments on commit 622089b

Please sign in to comment.