Skip to content
Open
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
29 changes: 29 additions & 0 deletions .changelog/1762113734.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
applies_to:
- server
authors:
- drganjoo
references:
- smithy-rs#3362
breaking: false
new_feature: true
bug_fix: false
---
Server SDK generation supports http/hyper@1. By default, the generated SDK will target http/hyper@0 based crates.

To generate the SDK for http/hyper@1, add the `http-1x` flag to the codegen section of smithy-build-template.json

```json
"plugins": {
"rust-server-codegen": {
"service": "<service shape ID with namespace>",
"module": "<generated sdk's package name>",
"moduleVersion": "<package version>",
"moduleDescription": "<package description>",
"codegen": {
"http-1x": true
}
}
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package software.amazon.smithy.rust.codegen.core.rustlang
import software.amazon.smithy.codegen.core.SymbolDependency
import software.amazon.smithy.codegen.core.SymbolDependencyContainer
import software.amazon.smithy.rust.codegen.core.smithy.ConstrainedModule
import software.amazon.smithy.rust.codegen.core.smithy.HttpVersion
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeConfig
import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.core.util.PANIC
Expand Down Expand Up @@ -369,6 +370,13 @@ data class CargoDependency(
CargoDependency("http-body-1x", CratesIo("1"), `package` = "http-body")
val HttpBodyUtil01x: CargoDependency =
CargoDependency("http-body-util", CratesIo("0.1.3"))
private val Hyper1x: CargoDependency = CargoDependency("hyper-1x", CratesIo("1"), `package` = "hyper")

fun hyper(runtimeConfig: RuntimeConfig) =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> CargoDependency("hyper", CratesIo("1"))
HttpVersion.Http0x -> CargoDependency("hyper", CratesIo("0.14.26"))
}

fun smithyAsync(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-async")

Expand All @@ -380,7 +388,17 @@ data class CargoDependency(

fun smithyEventStream(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-eventstream")

fun smithyHttp(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-http")
/**
* Returns the appropriate smithy-http dependency based on HTTP version.
*
* For HTTP 1.x: returns `aws-smithy-http` (latest version)
* For HTTP 0.x: returns `aws-smithy-legacy-http` (forked version supporting [email protected])
*/
fun smithyHttp(runtimeConfig: RuntimeConfig): CargoDependency =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> runtimeConfig.smithyRuntimeCrate("smithy-http")
HttpVersion.Http0x -> runtimeConfig.smithyRuntimeCrate("smithy-legacy-http")
}

fun smithyHttpClient(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-http-client")

Expand Down Expand Up @@ -408,8 +426,17 @@ data class CargoDependency(
fun smithyRuntimeApiTestUtil(runtimeConfig: RuntimeConfig) =
smithyRuntimeApi(runtimeConfig).toDevDependency().withFeature("test-util")

fun smithyTypes(runtimeConfig: RuntimeConfig) =
runtimeConfig.smithyRuntimeCrate("smithy-types").withFeature("http-body-1-x")
/**
* Returns smithy-types with the appropriate http-body feature.
*
* For HTTP 1.x: adds "http-body-1-x" feature
* For HTTP 0.x: adds "http-body-0-4-x" feature
*/
fun smithyTypes(runtimeConfig: RuntimeConfig): CargoDependency =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> runtimeConfig.smithyRuntimeCrate("smithy-types").withFeature("http-body-1-x")
HttpVersion.Http0x -> runtimeConfig.smithyRuntimeCrate("smithy-types").withFeature("http-body-0-4-x")
}

fun smithyXml(runtimeConfig: RuntimeConfig) = runtimeConfig.smithyRuntimeCrate("smithy-xml")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,30 @@ value class CrateVersionMap(
val map: Map<String, String>,
)

/**
* HTTP version to use for code generation.
*
* This determines which versions of http/http-body/hyper crates to use,
* as well as which smithy-http-server crate to use (legacy vs current).
*/
enum class HttpVersion {
/** HTTP 0.x: [email protected], [email protected], [email protected], aws-smithy-legacy-http-server */
Http0x,

/** HTTP 1.x: http@1, http-body@1, hyper@1, aws-smithy-http-server@1 */
Http1x,
}

/**
* Prefix & crate location for the runtime crates.
*/
data class RuntimeConfig(
val cratePrefix: String = "aws",
val runtimeCrateLocation: RuntimeCrateLocation = RuntimeCrateLocation.path("../"),
/**
* HTTP version to use for code generation. Defaults to Http1x as that is the default for Clients..
*/
val httpVersion: HttpVersion = HttpVersion.Http1x,
) {
companion object {
/**
Expand Down Expand Up @@ -289,10 +307,51 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null)
// Http1x types
val Http1x = CargoDependency.Http1x.toType()
val HttpBody1x = CargoDependency.HttpBody1x.toType()
val HttpRequest1x = Http1x.resolve("Request")
val HttpRequestBuilder1x = Http1x.resolve("request::Builder")
val HttpResponse1x = Http1x.resolve("Response")
val HttpResponseBuilder1x = Http1x.resolve("response::Builder")

/**
* Returns the appropriate http crate based on HTTP version.
*
* For HTTP 1.x: returns [email protected] crate
* For HTTP 0.x: returns [email protected] crate
*/
fun httpForConfig(runtimeConfig: RuntimeConfig): RuntimeType =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> Http1x
HttpVersion.Http0x -> Http
}

/**
* Returns the appropriate http::request::Builder based on HTTP version.
*
* For HTTP 1.x: returns [email protected] request::Builder
* For HTTP 0.x: returns [email protected] request::Builder
*/
fun httpRequestBuilderForConfig(runtimeConfig: RuntimeConfig): RuntimeType =
httpForConfig(runtimeConfig).resolve("request::Builder")

/**
* Returns the appropriate http::response::Builder based on HTTP version.
*
* For HTTP 1.x: returns [email protected] response::Builder
* For HTTP 0.x: returns [email protected] response::Builder
*/
fun httpResponseBuilderForConfig(runtimeConfig: RuntimeConfig): RuntimeType =
httpForConfig(runtimeConfig).resolve("response::Builder")

/**
* Returns the appropriate http-body crate module based on HTTP version.
*
* For HTTP 1.x: returns [email protected] crate
* For HTTP 0.x: returns [email protected] crate
*/
fun httpBodyForConfig(runtimeConfig: RuntimeConfig): RuntimeType =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> HttpBody1x
HttpVersion.Http0x -> HttpBody
}

fun hyperForConfig(runtimeConfig: RuntimeConfig) = CargoDependency.hyper(runtimeConfig).toType()

// external cargo dependency types
val Bytes = CargoDependency.Bytes.toType().resolve("Bytes")
Expand Down Expand Up @@ -337,6 +396,21 @@ data class RuntimeType(val path: String, val dependency: RustDependency? = null)

fun smithyRuntimeApi(runtimeConfig: RuntimeConfig) = CargoDependency.smithyRuntimeApi(runtimeConfig).toType()

/**
* Returns smithy-runtime-api with the appropriate HTTP version feature enabled.
*
* This is needed when accessing HTTP types from smithy-runtime-api like http::Request.
* For HTTP 1.x: adds "http-1x" feature
* For HTTP 0.x: adds "http-02x" feature
*
* Use this instead of smithyRuntimeApi() when you need HTTP type re-exports.
*/
fun smithyRuntimeApiWithHttpFeature(runtimeConfig: RuntimeConfig): RuntimeType =
when (runtimeConfig.httpVersion) {
HttpVersion.Http1x -> CargoDependency.smithyRuntimeApi(runtimeConfig).withFeature("http-1x").toType()
HttpVersion.Http0x -> CargoDependency.smithyRuntimeApi(runtimeConfig).withFeature("http-02x").toType()
}

fun smithyRuntimeApiClient(runtimeConfig: RuntimeConfig) =
CargoDependency.smithyRuntimeApiClient(runtimeConfig).toType()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,8 @@ class HttpBindingGenerator(
val codegenScope =
arrayOf(
"BuildError" to runtimeConfig.operationBuildError(),
HttpMessageType.REQUEST.name to RuntimeType.HttpRequestBuilder1x,
HttpMessageType.RESPONSE.name to RuntimeType.HttpResponseBuilder1x,
HttpMessageType.REQUEST.name to RuntimeType.httpRequestBuilderForConfig(runtimeConfig),
HttpMessageType.RESPONSE.name to RuntimeType.httpResponseBuilderForConfig(runtimeConfig),
"Shape" to shapeSymbol,
)
rustBlockTemplate(
Expand Down Expand Up @@ -712,7 +712,7 @@ class HttpBindingGenerator(
builder = builder.header("$headerName", header_value);

""",
"HeaderValue" to RuntimeType.Http1x.resolve("HeaderValue"),
"HeaderValue" to RuntimeType.httpForConfig(runtimeConfig).resolve("HeaderValue"),
"invalid_field_error" to renderErrorMessage("header_value"),
)
}
Expand Down Expand Up @@ -767,8 +767,8 @@ class HttpBindingGenerator(
}

""",
"HeaderValue" to RuntimeType.Http1x.resolve("HeaderValue"),
"HeaderName" to RuntimeType.Http1x.resolve("HeaderName"),
"HeaderValue" to RuntimeType.httpForConfig(runtimeConfig).resolve("HeaderValue"),
"HeaderName" to RuntimeType.httpForConfig(runtimeConfig).resolve("HeaderName"),
"invalid_header_name" to
OperationBuildError(runtimeConfig).invalidField(memberName) {
rust("""format!("`{k}` cannot be used as a header name: {err}")""")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import software.amazon.smithy.model.shapes.StringShape
import software.amazon.smithy.model.shapes.StructureShape
import software.amazon.smithy.model.shapes.UnionShape
import software.amazon.smithy.model.traits.EnumTrait
import software.amazon.smithy.rust.codegen.core.rustlang.CargoDependency
import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.core.rustlang.rust
import software.amazon.smithy.rust.codegen.core.rustlang.rustBlockTemplate
Expand Down Expand Up @@ -66,7 +65,6 @@ class HttpBoundProtocolPayloadGenerator(
private val smithyEventStream = RuntimeType.smithyEventStream(runtimeConfig)
private val codegenScope =
arrayOf(
"hyper" to CargoDependency.HyperWithStream.toType(),
"SdkBody" to RuntimeType.sdkBody(runtimeConfig),
"BuildError" to runtimeConfig.operationBuildError(),
"SmithyHttp" to RuntimeType.smithyHttp(runtimeConfig),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ class ServerAdditionalSettings private constructor(settings: List<AdditionalSett
return this
}

fun withHttp1x(enabled: Boolean = true): Builder {
settings.add(Http1x(enabled))
return this
}

override fun build(): ServerAdditionalSettings = ServerAdditionalSettings(settings)
}

Expand All @@ -139,6 +144,13 @@ class ServerAdditionalSettings private constructor(settings: List<AdditionalSett
.build()
}

private data class Http1x(val enabled: Boolean) : AdditionalSettings() {
override fun toObjectNode(): ObjectNode =
ObjectNode.builder()
.withMember("http-1x", enabled)
.build()
}

companion object {
fun builder() = Builder()
}
Expand Down
Loading
Loading