Add http-1x codegen support for server SDK generation#4376
Add http-1x codegen support for server SDK generation#4376drganjoo merged 9 commits intofeature/http-1.xfrom
Conversation
| val httpDeps = HttpDependencies.create(settings.codegenConfig.http1x, rustSymbolProviderConfig.runtimeConfig) | ||
| EventStreamSymbolProvider(rustSymbolProviderConfig.runtimeConfig, it, CodegenTarget.SERVER, httpDeps.smithyHttp) |
There was a problem hiding this comment.
I would recommend that we actually make RuntimeConfig "do the right thing". Or make it so that you MUST pass an http version setting when getting the dependencies that depend on it.
You could incorporate the http1x setting into RuntimeConfig potentially, then make things like smithyHttp http version aware?
I'm worried that the way the code works right now will be somewhat confusing for folks to deal with and create these really confusing compilation errors.
...ware/amazon/smithy/rust/codegen/server/smithy/customizations/ServerRequiredCustomizations.kt
Outdated
Show resolved
Hide resolved
| class StatusCodeSensitivity(private val sensitive: Boolean, private val smithyHttpServer: RuntimeType) { | ||
| private val codegenScope = | ||
| arrayOf( | ||
| "SmithyHttpServer" to ServerCargoDependency.smithyHttpServer(runtimeConfig).toType(), |
There was a problem hiding this comment.
I think we should probably have ServerCargoDependency.smithyHttpServerAuto that automatically gives you the right one. I think the http version would actually fit pretty naturally into RuntimeConfig as an optional parameter.
There was a problem hiding this comment.
But if you just want to ship things like it is, I get that. I'm just kinda worried about the long term fallout of having it be non-centralized especially as we eventually try to get rid of the old codegen settings.
5c29232 to
9bb8f0d
Compare
be0e38d to
13d6532
Compare
rcoh
left a comment
There was a problem hiding this comment.
nice! this is pretty clean. Nice work on this—left a few small comments but its really just naming and other bits of my own confusion
| /** | ||
| * HTTP version to use for code generation. Defaults to Http1x as that is the default for Clients.. | ||
| */ | ||
| val httpVersion: HttpVersion = HttpVersion.Http1x, |
There was a problem hiding this comment.
as long as there is a test somewhere this is fine, but I am a little bit worried about accidentally enabling this at some point
There was a problem hiding this comment.
Yes, we have a test Http1xDependencyTest.kt.SDK defaults to http-1x disabled, and dependencies are correct that ensures by default http1x == false and the generated SDK correctly depends on http/hyper@0.
| * For HTTP 1.x: returns http@1.x crate | ||
| * For HTTP 0.x: returns http@0.2.x crate | ||
| */ | ||
| fun httpForConfig(runtimeConfig: RuntimeConfig): RuntimeType = |
There was a problem hiding this comment.
personally, I'd consider dropping the ForConfig on all of these. obviously doesn't really matter either way, or call them auto
There was a problem hiding this comment.
I agree. But there are already member variables with similar names without the suffix, for example, val Http. They are used in the codebase to directly reference Http 0.x/1.x libraries (particularly in tests where we need to test specific library versions). I'd like to rename those, for example, from val Http to val Http0x to make it explicit that callers are choosing a specific library version. However, I prefer to handle this renaming in a separate CR; otherwise, a lot more files will be included in this CR. I'll create a follow-up CR for this refactoring.
For now, this CR has the Auto as the suffix instead of ForConfig.
| val HttpBodyUtil01x: CargoDependency = | ||
| CargoDependency("http-body-util", CratesIo("0.1.3")) | ||
|
|
||
| fun hyper(runtimeConfig: RuntimeConfig) = |
There was a problem hiding this comment.
I'd name every conditional dependency auto so its easy to find and its obvious if it is giving an automatic version
codegen-server-test/build.gradle.kts
Outdated
| service, | ||
| "$moduleName-http0x", | ||
| imports = imports, | ||
| extraCodegenConfig = extraCodegenConfig, |
There was a problem hiding this comment.
consider setting http-1x: false explicitly so this still works when we change the default
There was a problem hiding this comment.
I've done this deliberately as a safeguard to ensure that the default value of the flag is correct. If someone accidentally sets the http-1x flag to true, downstream tests, for example, codegen-server-test/eventstream/legacy would fail.
codegen-server-test/build.gradle.kts
Outdated
| * @param extraCodegenConfig Optional additional codegen config (goes inside "codegen": {}) | ||
| * @return List containing both http@0 (with -http0x suffix) and http@1 (no suffix) versions | ||
| */ | ||
| fun generateBothHttpVersions( |
There was a problem hiding this comment.
consider making this an extension function on CodegenTest so you can do codegenTests.flatMap { it.bothHttpVersions() }. A little bit more obvious & flexible I think
There was a problem hiding this comment.
Good idea - thanks.
| }) | ||
|
|
||
| let config = RpcV2CborServiceConfig::builder() | ||
| .layer(AddExtensionLayer::new(state.clone())) |
There was a problem hiding this comment.
I guess cleaner? but seems like this is actually likely to be harder to debug for people?
There was a problem hiding this comment.
but seems like this is actually likely to be harder to debug for people?
This approach matches our documentation. I wanted to have more sample points for AI tools to learn from.
| if (codegenContext.settings.runtimeConfig.httpVersion == HttpVersion.Http1x) { | ||
| rustWriter.rust( | ||
| """ | ||
| pub use crate::server::serve::serve; | ||
| """, | ||
| ) | ||
| } |
There was a problem hiding this comment.
not worth it here, but you can find an example in the client of doing automatic pub-use when a type is actually used
There was a problem hiding this comment.
Ah nice! I'll check the client code for future reference.
| } | ||
|
|
||
| // Check if parallel execution is enabled via environment variable | ||
| val runInParallel = System.getenv("PARALLEL_HTTP_TESTS")?.toBoolean() ?: false |
There was a problem hiding this comment.
No, not at the moment. I had added this to speed up the CI, but haven't tested this with Github. I'll remove this for now.
| @Test | ||
| fun `code compiles with custom validation exception using optionals`() { | ||
| serverIntegrationTest(completeTestModelWithOptionals) | ||
| serverIntegrationTest(completeTestModelWithOptionals, testCoverage = HttpTestType.AsConfigured) |
There was a problem hiding this comment.
note in this context AsConfigured isn't obvious which one is going to get picked. Does this basically mean "the default?"
There was a problem hiding this comment.
AsConfigured implies that serverIntegrationTest should not modify any settings and should use the codeGen flags as set by the caller. However, in practice, it has mostly been used for the default case. I'll rename it to Default to better reflect its actual usage.
| return listOf( | ||
| // http@0 version (legacy) - no http-1x flag, add -http0x suffix | ||
| this.copy( | ||
| module = "${this.module}-http0x", |
There was a problem hiding this comment.
shouldn't this set http-1x to false?
| this.copy( | ||
| extraCodegenConfig = | ||
| if (this.extraCodegenConfig?.isNotEmpty() == true) { | ||
| """"http-1x": true, ${this.extraCodegenConfig}""" |
There was a problem hiding this comment.
shouldn't this also produce a suffix?
This commit introduces comprehensive http-1x support to the server code generator,
enabling generation of server SDKs that work with either http@0.2.x or http@1.x
based on the
http-1xcodegen flag.Key Changes
New Infrastructure
HttpDependencies.kt: New data class that ensures cohesive HTTP dependency
selection, preventing accidental mixing of HTTP 0.x and 1.x versions. Provides
helper methods for accessing HTTP types (Request, Response, HeaderMap, etc.)
MultiVersionTestFailure.kt: Test infrastructure for tracking failures by
HTTP version, enabling tests to run against both http@0 and http@1
ServerCodegenConfig Updates
http1xboolean field to control HTTP version selection (config key:http-1x)false(http@0.2.x)ServerCodegenContext Updates
isHttp1()method to check if http-1x is enabledhttpDependencies()method to provide version-appropriate HTTP dependenciesthroughout code generation
ServerRequiredCustomizations
Protocol & Test Generator Updates
HTTP versions, with configurable test runtime mode (AS_CONFIGURED, BOTH, etc.)
references instead of hardcoded dependencies
Generator Updates
Updated generators to use HttpDependencies for type resolution:
Test Infrastructure
ability to run tests against both HTTP versions
based on http-1x flag
Core Changes
type generation
Testing
All protocol tests can now run against both HTTP versions to ensure compatibility.
Tests track failures by HTTP version for easier debugging.
Relates to #3362