Unverified Commit 3eaddcf7 authored by Zelda Hessler's avatar Zelda Hessler Committed by GitHub
Browse files

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

* add: default list of http versions
add: type alias for list of http versions
add: decorator to add desired http versions to property bag
fix: gradle warning for argument "model"
update: CHANGELOG

* fix: clippy lint

* update: use more accurate name for test RustCodegenDecorators
rename: HttpVersionListGenerator.kt to HttpVersionListCustomization.kt
update: HttpVersionListCustomization to grab versions from models when possible
fix: various docs issues reported by IDE
add: new "Extras" section to ServiceConfig
update: code broke by "Extras" change
add: tests for http version sniffing
parent beeca577
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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"
+1 −1
Original line number Diff line number Diff line
@@ -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) =
+69 −0
Original line number Diff line number Diff line
/*
 * 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")
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ class RetryConfigProviderConfig(codegenContext: CodegenContext) : ConfigCustomiz
                """retry_config: self.retry_config,""",
                *codegenScope
            )
            else -> emptySection
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ class SleepImplProviderConfig(codegenContext: CodegenContext) : ConfigCustomizat
                """sleep_impl: self.sleep_impl,""",
                *codegenScope
            )
            else -> emptySection
        }
    }
}
Loading