Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default list of http versions to request property bag #1258

Merged
merged 4 commits into from
Mar 17, 2022
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
6 changes: 6 additions & 0 deletions CHANGELOG.next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,9 @@ functional in a future update.
references = ["smithy-rs#724"]
meta = { "breaking" = true, "tada" = false, "bug" = false }
author = "Velfi"

[[smithy-rs]]
message = "HTTP request property bag now contains list of desired HTTP versions to use when making requests. This list is not currently used but will be in an upcoming update."
references = ["smithy-rs#1257"]
meta = { "breaking" = false, "tada" = false, "bug" = false }
author = "Velfi"
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class RustCodegenPlugin : SmithyBuildPlugin {
/** SymbolProvider
* When generating code, smithy types need to be converted into Rust types—that is the core role of the symbol provider
*
* The Symbol provider is composed of a base `SymbolVisitor` which handles the core funcitonality, then is layered
* The Symbol provider is composed of a base `SymbolVisitor` which handles the core functionality, then is layered
* with other symbol providers, documented inline, to handle the full scope of Smithy types.
*/
fun baseSymbolProvider(model: Model, serviceShape: ServiceShape, symbolVisitorConfig: SymbolVisitorConfig = DefaultConfig) =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

package software.amazon.smithy.rust.codegen.smithy.customizations

import software.amazon.smithy.aws.traits.protocols.AwsProtocolTrait
import software.amazon.smithy.model.shapes.OperationShape
import software.amazon.smithy.rust.codegen.rustlang.Writable
import software.amazon.smithy.rust.codegen.rustlang.rust
import software.amazon.smithy.rust.codegen.rustlang.writable
import software.amazon.smithy.rust.codegen.smithy.CodegenContext
import software.amazon.smithy.rust.codegen.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.customize.OperationCustomization
import software.amazon.smithy.rust.codegen.smithy.customize.OperationSection
import software.amazon.smithy.rust.codegen.util.getTrait
import software.amazon.smithy.rust.codegen.util.isEventStream

private fun RuntimeConfig.httpVersionModule(): RuntimeType =
RuntimeType("http_versions", this.runtimeCrate("http"), "aws_smithy_http")
private fun RuntimeConfig.defaultHttpVersionList(): RuntimeType =
this.httpVersionModule().member("DEFAULT_HTTP_VERSION_LIST")

class HttpVersionListCustomization(
private val codegenContext: CodegenContext,
private val operationShape: OperationShape
) : OperationCustomization() {
private val defaultHttpVersions = codegenContext.runtimeConfig.defaultHttpVersionList().fullyQualifiedName()

override fun section(section: OperationSection): Writable {
val awsProtocolTrait = codegenContext.serviceShape.getTrait<AwsProtocolTrait>()
val supportedHttpProtocolVersions = if (awsProtocolTrait == null) {
// No protocol trait was defined, use default http versions
"$defaultHttpVersions.clone()"
} else {
// Figure out whether we're dealing with an EventStream operation and fetch the corresponding list of desired HTTP versions
val versionList = if (operationShape.isEventStream(codegenContext.model)) awsProtocolTrait.eventStreamHttp else awsProtocolTrait.http
if (versionList.isEmpty()) {
// If no desired versions are specified, go with the default
"$defaultHttpVersions.clone()"
} else {
// otherwise, use the specified versions
"vec![${versionList.joinToString(",") { version -> mapHttpVersion(version) }}]"
}
}

return when (section) {
is OperationSection.MutateRequest -> writable {
rust(
"""
${section.request}.properties_mut().insert($supportedHttpProtocolVersions);
"""
)
}
else -> emptySection
}
}
}

// Map an ALPN protocol ID to a version from the `http` Rust crate
private fun mapHttpVersion(httpVersion: String): String {
return when (httpVersion) {
"http/1.1" -> "http::Version::HTTP_11"
"h2" -> "http::Version::HTTP_2"
else -> TODO("Unsupported HTTP version '$httpVersion', please check your model")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class RetryConfigProviderConfig(codegenContext: CodegenContext) : ConfigCustomiz
"""retry_config: self.retry_config,""",
*codegenScope
)
else -> emptySection
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class SleepImplProviderConfig(codegenContext: CodegenContext) : ConfigCustomizat
"""sleep_impl: self.sleep_impl,""",
*codegenScope
)
else -> emptySection
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ class TimeoutConfigProviderConfig(codegenContext: CodegenContext) : ConfigCustom
"""timeout_config: self.timeout_config,""",
*codegenScope
)
else -> emptySection
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.smithy.customizations.AllowLintsGener
import software.amazon.smithy.rust.codegen.smithy.customizations.CrateVersionGenerator
import software.amazon.smithy.rust.codegen.smithy.customizations.EndpointPrefixGenerator
import software.amazon.smithy.rust.codegen.smithy.customizations.HttpChecksumRequiredGenerator
import software.amazon.smithy.rust.codegen.smithy.customizations.HttpVersionListCustomization
import software.amazon.smithy.rust.codegen.smithy.customizations.IdempotencyTokenGenerator
import software.amazon.smithy.rust.codegen.smithy.customizations.SmithyTypesPubUseGenerator
import software.amazon.smithy.rust.codegen.smithy.generators.LibRsCustomization
Expand All @@ -30,10 +31,11 @@ class RequiredCustomizations : RustCodegenDecorator {
operation: OperationShape,
baseCustomizations: List<OperationCustomization>
): List<OperationCustomization> {
return baseCustomizations + IdempotencyTokenGenerator(codegenContext, operation) + EndpointPrefixGenerator(
codegenContext,
operation
) + HttpChecksumRequiredGenerator(codegenContext, operation)
return baseCustomizations +
IdempotencyTokenGenerator(codegenContext, operation) +
EndpointPrefixGenerator(codegenContext, operation) +
HttpChecksumRequiredGenerator(codegenContext, operation) +
HttpVersionListCustomization(codegenContext, operation)
}

override fun libRsCustomizations(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.util.logging.Logger
* [RustCodegenDecorator] allows downstream users to customize code generation.
*
* For example, AWS-specific code generation generates customizations required to support
* AWS services. A different downstream customer way wish to add a different set of derive
* AWS services. A different downstream customer may wish to add a different set of derive
* attributes to the generated classes.
*/
interface RustCodegenDecorator {
Expand Down Expand Up @@ -139,9 +139,9 @@ open class CombinedCodegenDecorator(decorators: List<RustCodegenDecorator>) : Ru
return orderedDecorators.forEach { it.extras(codegenContext, rustCrate) }
}

override fun transformModel(service: ServiceShape, baseModel: Model): Model {
return orderedDecorators.foldRight(baseModel) { decorator, model ->
decorator.transformModel(service, model)
override fun transformModel(service: ServiceShape, model: Model): Model {
return orderedDecorators.foldRight(model) { decorator, otherModel ->
decorator.transformModel(service, otherModel)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ sealed class ServiceConfig(name: String) : Section(name) {
* ```
*/
object BuilderBuild : ServiceConfig("BuilderBuild")

/**
* A section for extra functionality that needs to be defined with the config module
*/
object Extras : ServiceConfig("Extras")
}

fun ServiceShape.needsIdempotencyToken(model: Model): Boolean {
Expand Down Expand Up @@ -172,5 +177,8 @@ class ServiceConfigGenerator(private val customizations: List<ConfigCustomizatio
}
}
}
customizations.forEach {
it.section(ServiceConfig.Extras)(writer)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class JsonSerializerGenerator(
/** Expression representing the value to write to the JsonValueWriter */
val valueExpression: ValueExpression,
val shape: MemberShape,
/** Whether or not to serialize null values if the type is optional */
/** Whether to serialize null values if the type is optional */
val writeNulls: Boolean = false,
) {
companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import software.amazon.smithy.build.PluginContext
import software.amazon.smithy.codegen.core.Symbol
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.node.Node
import software.amazon.smithy.model.node.ObjectNode
import software.amazon.smithy.model.shapes.Shape
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.EnumDefinition
Expand Down Expand Up @@ -121,12 +122,12 @@ object TestWorkspace {
* "cargo test".runCommand(path)
* ```
*/
fun generatePluginContext(model: Model): Pair<PluginContext, Path> {
fun generatePluginContext(model: Model, additionalSettings: ObjectNode = ObjectNode.builder().build(), addModuleToEventStreamAllowList: Boolean = false): Pair<PluginContext, Path> {
val testDir = TestWorkspace.subproject()
val moduleName = "test_${testDir.nameWithoutExtension}"
val testPath = testDir.toPath()
val manifest = FileManifest.create(testPath)
val settings = Node.objectNodeBuilder()
var settingsBuilder = Node.objectNodeBuilder()
.withMember("module", Node.from(moduleName))
.withMember("moduleVersion", Node.from("1.0.0"))
.withMember("moduleDescription", Node.from("test"))
Expand All @@ -138,6 +139,18 @@ fun generatePluginContext(model: Model): Pair<PluginContext, Path> {
Node.from((TestRuntimeConfig.runtimeCrateLocation).path)
).build()
)

if (addModuleToEventStreamAllowList) {
settingsBuilder = settingsBuilder.withMember(
"codegen",
Node.objectNodeBuilder().withMember(
"eventStreamAllowList",
Node.fromStrings(moduleName)
).build()
)
}

val settings = settingsBuilder.merge(additionalSettings)
.build()
val pluginContext = PluginContext.builder().model(model).fileManifest(manifest).settings(settings).build()
return pluginContext to testPath
Expand All @@ -163,7 +176,7 @@ class TestWriterDelegator(private val fileManifest: FileManifest, symbolProvider

/**
* Setting `runClippy` to true can be helpful when debugging clippy failures, but
* should generally be set to false to avoid invalidating the Cargo cache between
* should generally be set to `false` to avoid invalidating the Cargo cache between
* every unit test run.
*/
fun TestWriterDelegator.compileAndTest(runClippy: Boolean = false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fun stubCustomization(name: String): ConfigCustomization {
$name: self.$name.unwrap_or(123),
"""
)
else -> emptySection
}
}
}
Expand Down
Loading