AWS SDK

AWS SDK

rev. ee474c7509d7728618c23068f3741e8e5b339ef9 (ignoring whitespace)

Files changed:

tmp-codegen-diff/aws-sdk/Cargo.lock

@@ -414,414 +473,474 @@
  434    434   
 "aws-types",
  435    435   
 "bytes",
  436    436   
 "bytes-utils",
  437    437   
 "convert_case",
  438    438   
 "fastrand 2.3.0",
  439    439   
 "futures-util",
  440    440   
 "http 0.2.12",
  441    441   
 "http 1.4.0",
  442    442   
 "http-body 0.4.6",
  443    443   
 "http-body 1.0.1",
         444  +
 "http-body-util",
  444    445   
 "percent-encoding",
  445    446   
 "pin-project-lite",
  446    447   
 "proptest",
  447    448   
 "regex-lite",
  448    449   
 "serde",
  449    450   
 "serde_json",
  450    451   
 "tokio",
  451    452   
 "tracing",
  452    453   
 "tracing-subscriber",
  453    454   
 "tracing-test",
@@ -543,544 +602,604 @@
  563    564   
 "aws-smithy-http",
  564    565   
 "aws-smithy-json",
  565    566   
 "aws-smithy-observability",
  566    567   
 "aws-smithy-runtime",
  567    568   
 "aws-smithy-runtime-api",
  568    569   
 "aws-smithy-types",
  569    570   
 "aws-types",
  570    571   
 "bytes",
  571    572   
 "fastrand 2.3.0",
  572    573   
 "http 0.2.12",
         574  +
 "http 1.4.0",
  573    575   
 "proptest",
  574    576   
 "regex-lite",
  575    577   
 "tokio",
  576    578   
 "tracing",
  577    579   
]
  578    580   
  579    581   
[[package]]
  580    582   
name = "aws-sdk-dynamodb"
  581    583   
version = "0.0.0-local"
  582    584   
dependencies = [
@@ -630,632 +689,692 @@
  650    652   
 "aws-smithy-http",
  651    653   
 "aws-smithy-json",
  652    654   
 "aws-smithy-observability",
  653    655   
 "aws-smithy-runtime",
  654    656   
 "aws-smithy-runtime-api",
  655    657   
 "aws-smithy-types",
  656    658   
 "aws-types",
  657    659   
 "bytes",
  658    660   
 "fastrand 2.3.0",
  659    661   
 "http 0.2.12",
         662  +
 "http 1.4.0",
  660    663   
 "proptest",
  661    664   
 "regex-lite",
  662    665   
 "tokio",
  663    666   
 "tracing",
  664    667   
]
  665    668   
  666    669   
[[package]]
  667    670   
name = "aws-sdk-glacier"
  668    671   
version = "0.0.0-local"
  669    672   
dependencies = [
@@ -814,817 +873,877 @@
  834    837   
 "aws-smithy-http-client",
  835    838   
 "aws-smithy-json",
  836    839   
 "aws-smithy-observability",
  837    840   
 "aws-smithy-runtime",
  838    841   
 "aws-smithy-runtime-api",
  839    842   
 "aws-smithy-types",
  840    843   
 "aws-smithy-xml",
  841    844   
 "aws-types",
  842    845   
 "fastrand 2.3.0",
  843    846   
 "http 0.2.12",
         847  +
 "http 1.4.0",
  844    848   
 "pretty_assertions",
  845    849   
 "proptest",
  846    850   
 "regex-lite",
  847    851   
 "tokio",
  848    852   
 "tracing",
  849    853   
 "tracing-test",
  850    854   
]
  851    855   
  852    856   
[[package]]
  853    857   
name = "aws-sdk-s3"
@@ -923,927 +1028,1035 @@
  943    947   
 "aws-smithy-http",
  944    948   
 "aws-smithy-json",
  945    949   
 "aws-smithy-observability",
  946    950   
 "aws-smithy-runtime",
  947    951   
 "aws-smithy-runtime-api",
  948    952   
 "aws-smithy-types",
  949    953   
 "aws-types",
  950    954   
 "bytes",
  951    955   
 "fastrand 2.3.0",
  952    956   
 "http 0.2.12",
         957  +
 "http 1.4.0",
  953    958   
 "proptest",
  954    959   
 "regex-lite",
  955    960   
 "tokio",
  956    961   
 "tracing",
  957    962   
]
  958    963   
  959    964   
[[package]]
  960    965   
name = "aws-sdk-sso"
  961    966   
version = "0.0.0-local"
  962    967   
dependencies = [
  963    968   
 "aws-credential-types",
  964    969   
 "aws-runtime",
  965    970   
 "aws-smithy-async",
  966    971   
 "aws-smithy-http",
  967    972   
 "aws-smithy-json",
  968    973   
 "aws-smithy-observability",
  969    974   
 "aws-smithy-runtime",
  970    975   
 "aws-smithy-runtime-api",
  971    976   
 "aws-smithy-types",
  972    977   
 "aws-types",
  973    978   
 "bytes",
  974    979   
 "fastrand 2.3.0",
  975    980   
 "http 0.2.12",
         981  +
 "http 1.4.0",
  976    982   
 "proptest",
  977    983   
 "regex-lite",
  978    984   
 "tokio",
  979    985   
 "tracing",
  980    986   
]
  981    987   
  982    988   
[[package]]
  983    989   
name = "aws-sdk-ssooidc"
  984    990   
version = "0.0.0-local"
  985    991   
dependencies = [
  986    992   
 "aws-credential-types",
  987    993   
 "aws-runtime",
  988    994   
 "aws-smithy-async",
  989    995   
 "aws-smithy-http",
  990    996   
 "aws-smithy-json",
  991    997   
 "aws-smithy-observability",
  992    998   
 "aws-smithy-runtime",
  993    999   
 "aws-smithy-runtime-api",
  994   1000   
 "aws-smithy-types",
  995   1001   
 "aws-types",
  996   1002   
 "bytes",
  997   1003   
 "fastrand 2.3.0",
  998   1004   
 "http 0.2.12",
        1005  +
 "http 1.4.0",
  999   1006   
 "proptest",
 1000   1007   
 "regex-lite",
 1001   1008   
 "tokio",
 1002   1009   
 "tracing",
 1003   1010   
]
 1004   1011   
 1005   1012   
[[package]]
 1006   1013   
name = "aws-sdk-sts"
 1007   1014   
version = "0.0.0-local"
 1008   1015   
dependencies = [
@@ -1053,1060 +1112,1120 @@
 1073   1080   
 "aws-smithy-http",
 1074   1081   
 "aws-smithy-json",
 1075   1082   
 "aws-smithy-observability",
 1076   1083   
 "aws-smithy-runtime",
 1077   1084   
 "aws-smithy-runtime-api",
 1078   1085   
 "aws-smithy-types",
 1079   1086   
 "aws-types",
 1080   1087   
 "bytes",
 1081   1088   
 "fastrand 2.3.0",
 1082   1089   
 "http 0.2.12",
        1090  +
 "http 1.4.0",
 1083   1091   
 "proptest",
 1084   1092   
 "regex-lite",
 1085   1093   
 "tokio",
 1086   1094   
 "tracing",
 1087   1095   
]
 1088   1096   
 1089   1097   
[[package]]
 1090   1098   
name = "aws-sdk-transcribestreaming"
 1091   1099   
version = "0.0.0-local"
 1092   1100   
dependencies = [
@@ -1159,1167 +1357,1364 @@
 1179   1187   
[[package]]
 1180   1188   
name = "aws-smithy-checksums"
 1181   1189   
version = "0.63.13"
 1182   1190   
dependencies = [
 1183   1191   
 "aws-smithy-http",
 1184   1192   
 "aws-smithy-types",
 1185   1193   
 "bytes",
 1186   1194   
 "bytes-utils",
 1187   1195   
 "crc-fast",
 1188   1196   
 "hex",
 1189         -
 "http 0.2.12",
 1190         -
 "http-body 0.4.6",
        1197  +
 "http 1.4.0",
        1198  +
 "http-body 1.0.1",
        1199  +
 "http-body-util",
 1191   1200   
 "md-5",
 1192   1201   
 "pin-project-lite",
 1193   1202   
 "pretty_assertions",
 1194   1203   
 "sha1",
 1195   1204   
 "sha2",
 1196   1205   
 "tokio",
 1197   1206   
 "tracing",
 1198   1207   
 "tracing-test",
 1199   1208   
]
 1200   1209   
 1201   1210   
[[package]]
 1202   1211   
name = "aws-smithy-compression"
 1203   1212   
version = "0.0.7"
 1204   1213   
dependencies = [
 1205   1214   
 "aws-smithy-runtime-api",
 1206   1215   
 "aws-smithy-types",
 1207   1216   
 "bytes",
 1208   1217   
 "bytes-utils",
 1209   1218   
 "flate2",
 1210   1219   
 "futures-util",
 1211         -
 "http 0.2.12",
 1212   1220   
 "http 1.4.0",
 1213         -
 "http-body 0.4.6",
 1214   1221   
 "http-body 1.0.1",
 1215   1222   
 "http-body-util",
 1216   1223   
 "pin-project-lite",
 1217   1224   
 "pretty_assertions",
 1218   1225   
 "tokio",
 1219   1226   
 "tracing",
 1220   1227   
]
 1221   1228   
 1222   1229   
[[package]]
 1223   1230   
name = "aws-smithy-dns"
 1224   1231   
version = "0.1.5"
 1225   1232   
dependencies = [
 1226   1233   
 "aws-smithy-runtime-api",
 1227   1234   
 "criterion",
 1228   1235   
 "hickory-resolver",
 1229   1236   
 "tokio",
 1230   1237   
]
 1231   1238   
 1232   1239   
[[package]]
 1233   1240   
name = "aws-smithy-eventstream"
 1234   1241   
version = "0.60.14"
 1235   1242   
dependencies = [
 1236   1243   
 "arbitrary",
 1237   1244   
 "aws-smithy-types",
 1238   1245   
 "bytes",
 1239   1246   
 "bytes-utils",
 1240   1247   
 "crc32fast",
 1241   1248   
 "criterion",
 1242   1249   
 "derive_arbitrary",
 1243   1250   
 "jemallocator",
 1244   1251   
 "mimalloc",
 1245   1252   
]
 1246   1253   
 1247   1254   
[[package]]
 1248   1255   
name = "aws-smithy-experimental"
 1249   1256   
version = "0.2.2"
 1250   1257   
 1251   1258   
[[package]]
 1252   1259   
name = "aws-smithy-http"
 1253         -
version = "0.62.6"
        1260  +
version = "0.63.0"
 1254   1261   
dependencies = [
 1255   1262   
 "async-stream",
 1256   1263   
 "aws-smithy-eventstream",
 1257   1264   
 "aws-smithy-runtime-api",
 1258   1265   
 "aws-smithy-types",
 1259   1266   
 "bytes",
 1260   1267   
 "bytes-utils",
 1261   1268   
 "futures-core",
 1262   1269   
 "futures-util",
 1263         -
 "http 0.2.12",
 1264   1270   
 "http 1.4.0",
 1265         -
 "http-body 0.4.6",
 1266         -
 "hyper 0.14.32",
        1271  +
 "http-body 1.0.1",
        1272  +
 "http-body-util",
        1273  +
 "hyper 1.8.1",
 1267   1274   
 "percent-encoding",
 1268   1275   
 "pin-project-lite",
 1269   1276   
 "pin-utils",
 1270   1277   
 "proptest",
 1271   1278   
 "tokio",
 1272   1279   
 "tracing",
 1273   1280   
]
 1274   1281   
 1275   1282   
[[package]]
 1276   1283   
name = "aws-smithy-http-client"
 1277   1284   
version = "1.1.5"
 1278   1285   
dependencies = [
 1279   1286   
 "aws-smithy-async",
 1280   1287   
 "aws-smithy-protocol-test",
 1281   1288   
 "aws-smithy-runtime-api",
 1282   1289   
 "aws-smithy-types",
 1283   1290   
 "base64 0.22.1",
 1284   1291   
 "bytes",
 1285   1292   
 "h2 0.3.27",
 1286   1293   
 "h2 0.4.13",
 1287   1294   
 "http 0.2.12",
 1288   1295   
 "http 1.4.0",
 1289   1296   
 "http-body 0.4.6",
 1290   1297   
 "http-body 1.0.1",
 1291   1298   
 "http-body-util",
 1292   1299   
 "hyper 0.14.32",
 1293   1300   
 "hyper 1.8.1",
 1294   1301   
 "hyper-rustls 0.24.2",
 1295   1302   
 "hyper-rustls 0.27.7",
 1296   1303   
 "hyper-util",
 1297   1304   
 "indexmap",
 1298   1305   
 "pin-project-lite",
 1299   1306   
 "rustls 0.21.12",
 1300   1307   
 "rustls 0.23.36",
 1301   1308   
 "rustls-native-certs",
 1302   1309   
 "rustls-pemfile",
 1303   1310   
 "rustls-pki-types",
 1304   1311   
 "s2n-tls",
 1305   1312   
 "s2n-tls-hyper",
 1306   1313   
 "s2n-tls-tokio",
 1307   1314   
 "serde",
 1308   1315   
 "serde_json",
 1309   1316   
 "serial_test",
 1310   1317   
 "tokio",
 1311   1318   
 "tokio-rustls 0.26.4",
 1312   1319   
 "tower",
 1313   1320   
 "tracing",
 1314   1321   
]
 1315   1322   
 1316   1323   
[[package]]
 1317   1324   
name = "aws-smithy-json"
 1318         -
version = "0.61.9"
        1325  +
version = "0.62.0"
 1319   1326   
dependencies = [
 1320   1327   
 "aws-smithy-types",
 1321   1328   
 "proptest",
 1322   1329   
 "serde_json",
 1323   1330   
]
 1324   1331   
 1325   1332   
[[package]]
 1326   1333   
name = "aws-smithy-legacy-http"
 1327         -
version = "0.62.6"
        1334  +
version = "0.62.7"
 1328   1335   
dependencies = [
 1329   1336   
 "async-stream",
 1330   1337   
 "aws-smithy-eventstream",
 1331   1338   
 "aws-smithy-runtime-api",
 1332   1339   
 "aws-smithy-types",
 1333   1340   
 "bytes",
 1334   1341   
 "bytes-utils",
 1335   1342   
 "futures-core",
 1336   1343   
 "futures-util",
 1337   1344   
 "http 0.2.12",
@@ -1365,1372 +1457,1466 @@
 1385   1392   
[[package]]
 1386   1393   
name = "aws-smithy-protocol-test"
 1387   1394   
version = "0.63.7"
 1388   1395   
dependencies = [
 1389   1396   
 "assert-json-diff",
 1390   1397   
 "aws-smithy-runtime-api",
 1391   1398   
 "base64-simd",
 1392   1399   
 "cbor-diag",
 1393   1400   
 "ciborium",
 1394   1401   
 "http 0.2.12",
        1402  +
 "http 1.4.0",
 1395   1403   
 "pretty_assertions",
 1396   1404   
 "regex-lite",
 1397   1405   
 "roxmltree",
 1398   1406   
 "serde_json",
 1399   1407   
 "thiserror 2.0.17",
 1400   1408   
]
 1401   1409   
 1402   1410   
[[package]]
 1403   1411   
name = "aws-smithy-query"
 1404   1412   
version = "0.60.9"
 1405   1413   
dependencies = [
 1406   1414   
 "aws-smithy-types",
 1407   1415   
 "urlencoding",
 1408   1416   
]
 1409   1417   
 1410   1418   
[[package]]
 1411   1419   
name = "aws-smithy-runtime"
 1412   1420   
version = "1.9.8"
 1413   1421   
dependencies = [
 1414   1422   
 "approx",
 1415   1423   
 "aws-smithy-async",
 1416   1424   
 "aws-smithy-http",
 1417   1425   
 "aws-smithy-http-client",
 1418   1426   
 "aws-smithy-observability",
 1419   1427   
 "aws-smithy-runtime-api",
 1420   1428   
 "aws-smithy-types",
 1421   1429   
 "bytes",
 1422   1430   
 "fastrand 2.3.0",
 1423   1431   
 "futures-util",
 1424   1432   
 "http 0.2.12",
 1425   1433   
 "http 1.4.0",
 1426   1434   
 "http-body 0.4.6",
 1427   1435   
 "http-body 1.0.1",
        1436  +
 "http-body-util",
 1428   1437   
 "hyper 0.14.32",
 1429   1438   
 "pin-project-lite",
 1430   1439   
 "pin-utils",
 1431   1440   
 "pretty_assertions",
 1432   1441   
 "tokio",
 1433   1442   
 "tracing",
 1434   1443   
 "tracing-subscriber",
 1435   1444   
 "tracing-test",
 1436   1445   
]
 1437   1446   

tmp-codegen-diff/aws-sdk/sdk/aws-config/Cargo.toml

@@ -19,19 +110,110 @@
   39     39   
url = "2.5.4"
   40     40   
fastrand = "2.3.0"
   41     41   
   42     42   
[dependencies.aws-credential-types]
   43     43   
path = "../aws-credential-types"
   44     44   
features = ["test-util"]
   45     45   
version = "1.2.11"
   46     46   
   47     47   
[dependencies.aws-runtime]
   48     48   
path = "../aws-runtime"
   49         -
version = "1.5.18"
          49  +
version = "1.6.0"
   50     50   
   51     51   
[dependencies.aws-sdk-sts]
   52     52   
path = "../sts"
   53     53   
default-features = false
   54     54   
version = "0.0.0-local"
   55     55   
   56     56   
[dependencies.aws-smithy-async]
   57     57   
path = "../aws-smithy-async"
   58         -
version = "1.2.7"
          58  +
version = "1.2.8"
   59     59   
   60     60   
[dependencies.aws-smithy-http]
   61     61   
path = "../aws-smithy-http"
   62         -
version = "0.62.6"
          62  +
version = "0.63.0"
   63     63   
   64     64   
[dependencies.aws-smithy-json]
   65     65   
path = "../aws-smithy-json"
   66         -
version = "0.61.9"
          66  +
version = "0.62.0"
   67     67   
   68     68   
[dependencies.aws-smithy-runtime]
   69     69   
path = "../aws-smithy-runtime"
   70     70   
features = ["client"]
   71         -
version = "1.9.8"
          71  +
version = "1.10.0"
   72     72   
   73     73   
[dependencies.aws-smithy-runtime-api]
   74     74   
path = "../aws-smithy-runtime-api"
   75     75   
features = ["client"]
   76         -
version = "1.10.0"
          76  +
version = "1.11.0"
   77     77   
   78     78   
[dependencies.aws-smithy-types]
   79     79   
path = "../aws-smithy-types"
   80         -
version = "1.3.6"
          80  +
version = "1.4.0"
   81     81   
   82     82   
[dependencies.aws-types]
   83     83   
path = "../aws-types"
   84     84   
version = "1.3.11"
   85     85   
   86     86   
[dependencies.time]
   87     87   
version = "0.3.4"
   88     88   
features = ["parsing"]
   89     89   
   90     90   
[dependencies.tokio]
@@ -126,126 +187,187 @@
  146    146   
features = ["std", "std_rng"]
  147    147   
optional = true
  148    148   
  149    149   
[dev-dependencies]
  150    150   
tracing-test = "0.2.4"
  151    151   
serde_json = "1"
  152    152   
  153    153   
[dev-dependencies.aws-smithy-async]
  154    154   
path = "../aws-smithy-async"
  155    155   
features = ["rt-tokio", "test-util"]
  156         -
version = "1.2.7"
         156  +
version = "1.2.8"
  157    157   
  158    158   
[dev-dependencies.aws-smithy-http-client]
  159    159   
path = "../aws-smithy-http-client"
  160    160   
features = ["default-client", "test-util"]
  161         -
version = "1.1.5"
         161  +
version = "1.1.6"
  162    162   
  163    163   
[dev-dependencies.aws-smithy-runtime]
  164    164   
path = "../aws-smithy-runtime"
  165    165   
features = ["client", "test-util"]
  166         -
version = "1.9.8"
         166  +
version = "1.10.0"
  167    167   
  168    168   
[dev-dependencies.aws-smithy-runtime-api]
  169    169   
path = "../aws-smithy-runtime-api"
  170    170   
features = ["test-util"]
  171         -
version = "1.10.0"
         171  +
version = "1.11.0"
  172    172   
  173    173   
[dev-dependencies.futures-util]
  174    174   
version = "0.3.29"
  175    175   
default-features = false
  176    176   
  177    177   
[dev-dependencies.tracing-subscriber]
  178    178   
version = "0.3.16"
  179    179   
features = ["fmt", "json"]
  180    180   
  181    181   
[dev-dependencies.tokio]

tmp-codegen-diff/aws-sdk/sdk/aws-credential-types/Cargo.toml

@@ -1,1 +50,50 @@
   19     19   
   20     20   
[features]
   21     21   
hardcoded-credentials = []
   22     22   
test-util = ["aws-smithy-runtime-api/test-util"]
   23     23   
   24     24   
[dependencies]
   25     25   
zeroize = "1.7.0"
   26     26   
   27     27   
[dependencies.aws-smithy-async]
   28     28   
path = "../aws-smithy-async"
   29         -
version = "1.2.7"
          29  +
version = "1.2.8"
   30     30   
   31     31   
[dependencies.aws-smithy-types]
   32     32   
path = "../aws-smithy-types"
   33         -
version = "1.3.6"
          33  +
version = "1.4.0"
   34     34   
   35     35   
[dependencies.aws-smithy-runtime-api]
   36     36   
path = "../aws-smithy-runtime-api"
   37     37   
features = ["client", "http-auth"]
   38         -
version = "1.10.0"
          38  +
version = "1.11.0"
   39     39   
   40     40   
[dev-dependencies]
   41     41   
async-trait = "0.1.74"
   42     42   
   43     43   
[dev-dependencies.aws-smithy-runtime-api]
   44     44   
path = "../aws-smithy-runtime-api"
   45     45   
features = ["test-util"]
   46         -
version = "1.10.0"
          46  +
version = "1.11.0"
   47     47   
   48     48   
[dev-dependencies.tokio]
   49     49   
version = "1.23.1"
   50     50   
features = ["full", "test-util", "rt"]

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/Cargo.toml

@@ -1,1 +145,145 @@
    1      1   
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
    2      2   
[package]
    3      3   
name = "aws-runtime"
    4         -
version = "1.5.18"
           4  +
version = "1.6.0"
    5      5   
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>"]
    6      6   
description = "Runtime support code for the AWS SDK. This crate isn't intended to be used directly."
    7      7   
edition = "2021"
    8      8   
license = "Apache-2.0"
    9      9   
repository = "https://github.com/smithy-lang/smithy-rs"
   10     10   
rust-version = "1.88"
   11     11   
[package.metadata.docs.rs]
   12     12   
all-features = true
   13     13   
targets = ["x86_64-unknown-linux-gnu"]
   14     14   
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
   15     15   
rustdoc-args = ["--cfg", "docsrs"]
   16     16   
   17     17   
[package.metadata.smithy-rs-release-tooling]
   18     18   
stable = true
   19     19   
   20     20   
[features]
   21     21   
event-stream = ["dep:aws-smithy-eventstream", "aws-sigv4/sign-eventstream"]
   22     22   
http-02x = []
   23         -
http-1x = ["dep:http-1x", "dep:http-body-1x"]
          23  +
http-1x = []
   24     24   
test-util = ["dep:regex-lite"]
   25     25   
sigv4a = ["aws-sigv4/sigv4a"]
   26     26   
   27     27   
[dependencies]
   28     28   
bytes = "1.10.0"
   29     29   
fastrand = "2.3.0"
   30     30   
percent-encoding = "2.3.1"
   31     31   
pin-project-lite = "0.2.14"
   32     32   
tracing = "0.1.40"
   33     33   
   34     34   
[dependencies.aws-credential-types]
   35     35   
path = "../aws-credential-types"
   36     36   
version = "1.2.11"
   37     37   
   38     38   
[dependencies.aws-sigv4]
   39     39   
path = "../aws-sigv4"
   40     40   
features = ["http0-compat"]
   41         -
version = "1.3.7"
          41  +
version = "1.3.8"
   42     42   
   43     43   
[dependencies.aws-smithy-async]
   44     44   
path = "../aws-smithy-async"
   45         -
version = "1.2.7"
          45  +
version = "1.2.8"
   46     46   
   47     47   
[dependencies.aws-smithy-eventstream]
   48     48   
path = "../aws-smithy-eventstream"
   49     49   
optional = true
   50         -
version = "0.60.14"
          50  +
version = "0.60.15"
   51     51   
   52     52   
[dependencies.aws-smithy-http]
   53     53   
path = "../aws-smithy-http"
   54         -
version = "0.62.6"
          54  +
version = "0.63.0"
   55     55   
   56     56   
[dependencies.aws-smithy-runtime]
   57     57   
path = "../aws-smithy-runtime"
   58     58   
features = ["client"]
   59         -
version = "1.9.8"
          59  +
version = "1.10.0"
   60     60   
   61     61   
[dependencies.aws-smithy-runtime-api]
   62     62   
path = "../aws-smithy-runtime-api"
   63         -
features = ["client"]
   64         -
version = "1.10.0"
          63  +
features = ["client", "http-1x"]
          64  +
version = "1.11.0"
   65     65   
   66     66   
[dependencies.aws-smithy-types]
   67     67   
path = "../aws-smithy-types"
   68         -
version = "1.3.6"
          68  +
features = ["http-body-1-x"]
          69  +
version = "1.4.0"
   69     70   
   70     71   
[dependencies.aws-types]
   71     72   
path = "../aws-types"
   72     73   
version = "1.3.11"
   73     74   
   74     75   
[dependencies.http-02x]
   75     76   
package = "http"
   76         -
version = "0.2.9"
          77  +
version = "0.2.12"
   77     78   
   78     79   
[dependencies.http-body-04x]
   79     80   
package = "http-body"
   80         -
version = "0.4.5"
          81  +
version = "0.4.6"
   81     82   
   82     83   
[dependencies.http-1x]
   83     84   
package = "http"
   84         -
version = "1.1.0"
   85         -
optional = true
          85  +
version = "1.3.1"
   86     86   
   87     87   
[dependencies.http-body-1x]
   88     88   
package = "http-body"
   89         -
version = "1.0.0"
   90         -
optional = true
          89  +
version = "1.0.1"
   91     90   
   92     91   
[dependencies.regex-lite]
   93     92   
version = "0.1.5"
   94     93   
optional = true
   95     94   
   96     95   
[dependencies.uuid]
   97     96   
version = "1"
   98     97   
   99     98   
[dev-dependencies]
  100     99   
arbitrary = "1.3"
  101    100   
bytes-utils = "0.1.2"
  102    101   
convert_case = "0.6.0"
         102  +
http-body-util = "0.1.3"
  103    103   
proptest = "1.2"
  104    104   
serde_json = "1"
  105    105   
tracing-test = "0.2.4"
  106    106   
  107    107   
[dev-dependencies.aws-credential-types]
  108    108   
path = "../aws-credential-types"
  109    109   
features = ["test-util"]
  110    110   
version = "1.2.11"
  111    111   
  112    112   
[dev-dependencies.aws-smithy-async]
  113    113   
path = "../aws-smithy-async"
  114    114   
features = ["test-util"]
  115         -
version = "1.2.7"
         115  +
version = "1.2.8"
  116    116   
  117    117   
[dev-dependencies.aws-smithy-protocol-test]
  118    118   
path = "../aws-smithy-protocol-test"
  119         -
version = "0.63.7"
         119  +
version = "0.63.8"
  120    120   
  121    121   
[dev-dependencies.aws-smithy-runtime-api]
  122    122   
path = "../aws-smithy-runtime-api"
  123         -
features = ["test-util"]
  124         -
version = "1.10.0"
         123  +
features = ["test-util", "http-1x"]
         124  +
version = "1.11.0"
  125    125   
  126    126   
[dev-dependencies.aws-smithy-types]
  127    127   
path = "../aws-smithy-types"
  128    128   
features = ["test-util"]
  129         -
version = "1.3.6"
         129  +
version = "1.4.0"
  130    130   
  131    131   
[dev-dependencies.futures-util]
  132    132   
version = "0.3.29"
  133    133   
default-features = false
  134    134   
  135    135   
[dev-dependencies.serde]
  136    136   
version = "1"
  137    137   
features = ["derive"]
  138    138   
  139    139   
[dev-dependencies.tokio]

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/auth.rs

@@ -269,269 +329,329 @@
  289    289   
        .and_then(Document::as_object)
  290    290   
        .and_then(|config| config.get(field_name))
  291    291   
}
  292    292   
  293    293   
fn apply_signing_instructions(
  294    294   
    instructions: SigningInstructions,
  295    295   
    request: &mut HttpRequest,
  296    296   
) -> Result<(), BoxError> {
  297    297   
    let (new_headers, new_query) = instructions.into_parts();
  298    298   
    for header in new_headers.into_iter() {
  299         -
        let mut value = http_02x::HeaderValue::from_str(header.value()).unwrap();
         299  +
        let mut value = http_1x::HeaderValue::from_str(header.value()).unwrap();
  300    300   
        value.set_sensitive(header.sensitive());
  301    301   
        request.headers_mut().insert(header.name(), value);
  302    302   
    }
  303    303   
  304    304   
    if !new_query.is_empty() {
  305    305   
        let mut query = aws_smithy_http::query_writer::QueryWriter::new_from_string(request.uri())?;
  306    306   
        for (name, value) in new_query {
  307    307   
            query.insert(name, &value);
  308    308   
        }
  309    309   
        request.set_uri(query.build_uri())?;

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/content_encoding.rs

@@ -1,1 +46,48 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use aws_smithy_types::config_bag::{Storable, StoreReplace};
    7      7   
use bytes::{Bytes, BytesMut};
    8         -
use http_02x::{HeaderMap, HeaderValue};
    9         -
use http_body_04x::{Body, SizeHint};
   10      8   
use pin_project_lite::pin_project;
   11      9   
   12     10   
use std::pin::Pin;
   13     11   
use std::task::{Context, Poll};
   14     12   
   15     13   
const CRLF: &str = "\r\n";
          14  +
const CRLF_RAW: &[u8] = b"\r\n";
          15  +
   16     16   
const CHUNK_TERMINATOR: &str = "0\r\n";
          17  +
const CHUNK_TERMINATOR_RAW: &[u8] = b"0\r\n";
          18  +
   17     19   
const TRAILER_SEPARATOR: &[u8] = b":";
   18     20   
   19     21   
/// Content encoding header value constants
   20     22   
pub mod header_value {
   21     23   
    /// Header value denoting "aws-chunked" encoding
   22     24   
    pub const AWS_CHUNKED: &str = "aws-chunked";
   23     25   
}
   24     26   
   25     27   
/// Options used when constructing an [`AwsChunkedBody`].
   26     28   
#[derive(Clone, Debug, Default)]
@@ -140,142 +415,691 @@
  160    162   
    pub fn new(body: Inner, options: AwsChunkedBodyOptions) -> Self {
  161    163   
        Self {
  162    164   
            inner: body,
  163    165   
            state: AwsChunkedBodyState::WritingChunkSize,
  164    166   
            options,
  165    167   
            inner_body_bytes_read_so_far: 0,
  166    168   
        }
  167    169   
    }
  168    170   
}
  169    171   
  170         -
fn get_unsigned_chunk_bytes_length(payload_length: u64) -> u64 {
  171         -
    let hex_repr_len = int_log16(payload_length);
  172         -
    hex_repr_len + CRLF.len() as u64 + payload_length + CRLF.len() as u64
  173         -
}
  174         -
  175         -
/// Writes trailers out into a `string` and then converts that `String` to a `Bytes` before
  176         -
/// returning.
  177         -
///
  178         -
/// - Trailer names are separated by a single colon only, no space.
  179         -
/// - Trailer names with multiple values will be written out one line per value, with the name
  180         -
///   appearing on each line.
  181         -
fn trailers_as_aws_chunked_bytes(
  182         -
    trailer_map: Option<HeaderMap>,
  183         -
    estimated_length: u64,
  184         -
) -> BytesMut {
  185         -
    if let Some(trailer_map) = trailer_map {
  186         -
        let mut current_header_name = None;
  187         -
        let mut trailers = BytesMut::with_capacity(estimated_length.try_into().unwrap_or_default());
  188         -
  189         -
        for (header_name, header_value) in trailer_map.into_iter() {
  190         -
            // When a header has multiple values, the name only comes up in iteration the first time
  191         -
            // we see it. Therefore, we need to keep track of the last name we saw and fall back to
  192         -
            // it when `header_name == None`.
  193         -
            current_header_name = header_name.or(current_header_name);
  194         -
  195         -
            // In practice, this will always exist, but `if let` is nicer than unwrap
  196         -
            if let Some(header_name) = current_header_name.as_ref() {
  197         -
                trailers.extend_from_slice(header_name.as_ref());
  198         -
                trailers.extend_from_slice(TRAILER_SEPARATOR);
  199         -
                trailers.extend_from_slice(header_value.as_bytes());
  200         -
                trailers.extend_from_slice(CRLF.as_bytes());
  201         -
            }
  202         -
        }
  203         -
  204         -
        trailers
  205         -
    } else {
  206         -
        BytesMut::new()
  207         -
    }
  208         -
}
  209         -
  210         -
/// Given an optional `HeaderMap`, calculate the total number of bytes required to represent the
  211         -
/// `HeaderMap`. If no `HeaderMap` is given as input, return 0.
  212         -
///
  213         -
/// - Trailer names are separated by a single colon only, no space.
  214         -
/// - Trailer names with multiple values will be written out one line per value, with the name
  215         -
///   appearing on each line.
  216         -
fn total_rendered_length_of_trailers(trailer_map: Option<&HeaderMap>) -> u64 {
  217         -
    match trailer_map {
  218         -
        Some(trailer_map) => trailer_map
  219         -
            .iter()
  220         -
            .map(|(trailer_name, trailer_value)| {
  221         -
                trailer_name.as_str().len()
  222         -
                    + TRAILER_SEPARATOR.len()
  223         -
                    + trailer_value.len()
  224         -
                    + CRLF.len()
  225         -
            })
  226         -
            .sum::<usize>() as u64,
  227         -
        None => 0,
  228         -
    }
  229         -
}
  230         -
  231         -
impl<Inner> Body for AwsChunkedBody<Inner>
         172  +
impl<Inner> http_body_04x::Body for AwsChunkedBody<Inner>
  232    173   
where
  233         -
    Inner: Body<Data = Bytes, Error = aws_smithy_types::body::Error>,
         174  +
    Inner: http_body_04x::Body<Data = Bytes, Error = aws_smithy_types::body::Error>,
  234    175   
{
  235    176   
    type Data = Bytes;
  236    177   
    type Error = aws_smithy_types::body::Error;
  237    178   
  238    179   
    fn poll_data(
  239    180   
        self: Pin<&mut Self>,
  240    181   
        cx: &mut Context<'_>,
  241    182   
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
  242    183   
        tracing::trace!(state = ?self.state, "polling AwsChunkedBody");
  243    184   
        let mut this = self.project();
  244    185   
  245    186   
        match *this.state {
  246    187   
            AwsChunkedBodyState::WritingChunkSize => {
  247    188   
                if this.options.stream_length == 0 {
  248    189   
                    // If the stream is empty, we skip to writing trailers after writing the CHUNK_TERMINATOR.
  249    190   
                    *this.state = AwsChunkedBodyState::WritingTrailers;
  250    191   
                    tracing::trace!("stream is empty, writing chunk terminator");
  251    192   
                    Poll::Ready(Some(Ok(Bytes::from([CHUNK_TERMINATOR].concat()))))
  252    193   
                } else {
  253    194   
                    *this.state = AwsChunkedBodyState::WritingChunk;
  254    195   
                    // A chunk must be prefixed by chunk size in hexadecimal
  255    196   
                    let chunk_size = format!("{:X?}{CRLF}", this.options.stream_length);
  256    197   
                    tracing::trace!(%chunk_size, "writing chunk size");
  257    198   
                    let chunk_size = Bytes::from(chunk_size);
  258    199   
                    Poll::Ready(Some(Ok(chunk_size)))
  259    200   
                }
  260    201   
            }
  261    202   
            AwsChunkedBodyState::WritingChunk => match this.inner.poll_data(cx) {
  262    203   
                Poll::Ready(Some(Ok(data))) => {
  263    204   
                    tracing::trace!(len = data.len(), "writing chunk data");
  264    205   
                    *this.inner_body_bytes_read_so_far += data.len();
  265    206   
                    Poll::Ready(Some(Ok(data)))
  266    207   
                }
  267    208   
                Poll::Ready(None) => {
  268    209   
                    let actual_stream_length = *this.inner_body_bytes_read_so_far as u64;
  269    210   
                    let expected_stream_length = this.options.stream_length;
  270    211   
                    if actual_stream_length != expected_stream_length {
  271    212   
                        let err = Box::new(AwsChunkedBodyError::StreamLengthMismatch {
  272    213   
                            actual: actual_stream_length,
  273    214   
                            expected: expected_stream_length,
  274    215   
                        });
  275    216   
                        return Poll::Ready(Some(Err(err)));
  276    217   
                    };
  277    218   
  278    219   
                    tracing::trace!("no more chunk data, writing CRLF and chunk terminator");
  279    220   
                    *this.state = AwsChunkedBodyState::WritingTrailers;
  280    221   
                    // Since we wrote chunk data, we end it with a CRLF and since we only write
  281    222   
                    // a single chunk, we write the CHUNK_TERMINATOR immediately after
  282    223   
                    Poll::Ready(Some(Ok(Bytes::from([CRLF, CHUNK_TERMINATOR].concat()))))
  283    224   
                }
  284    225   
                Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
  285    226   
                Poll::Pending => Poll::Pending,
  286    227   
            },
  287    228   
            AwsChunkedBodyState::WritingTrailers => {
  288    229   
                return match this.inner.poll_trailers(cx) {
  289    230   
                    Poll::Ready(Ok(trailers)) => {
  290    231   
                        *this.state = AwsChunkedBodyState::Closed;
  291         -
                        let expected_length = total_rendered_length_of_trailers(trailers.as_ref());
         232  +
                        let expected_length =
         233  +
                            http_02x_utils::total_rendered_length_of_trailers(trailers.as_ref());
  292    234   
                        let actual_length = this.options.total_trailer_length();
  293    235   
  294    236   
                        if expected_length != actual_length {
  295    237   
                            let err =
  296    238   
                                Box::new(AwsChunkedBodyError::ReportedTrailerLengthMismatch {
  297    239   
                                    actual: actual_length,
  298    240   
                                    expected: expected_length,
  299    241   
                                });
  300    242   
                            return Poll::Ready(Some(Err(err)));
  301    243   
                        }
  302    244   
  303         -
                        let mut trailers =
  304         -
                            trailers_as_aws_chunked_bytes(trailers, actual_length + 1);
         245  +
                        let mut trailers = http_02x_utils::trailers_as_aws_chunked_bytes(
         246  +
                            trailers,
         247  +
                            actual_length + 1,
         248  +
                        );
  305    249   
                        // Insert the final CRLF to close the body
  306    250   
                        trailers.extend_from_slice(CRLF.as_bytes());
  307    251   
  308    252   
                        Poll::Ready(Some(Ok(trailers.into())))
  309    253   
                    }
  310    254   
                    Poll::Pending => Poll::Pending,
  311    255   
                    Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))),
  312    256   
                };
  313    257   
            }
  314    258   
            AwsChunkedBodyState::Closed => Poll::Ready(None),
  315    259   
        }
  316    260   
    }
  317    261   
  318    262   
    fn poll_trailers(
  319    263   
        self: Pin<&mut Self>,
  320    264   
        _cx: &mut Context<'_>,
  321         -
    ) -> Poll<Result<Option<HeaderMap<HeaderValue>>, Self::Error>> {
         265  +
    ) -> Poll<Result<Option<http_02x::HeaderMap<http_02x::HeaderValue>>, Self::Error>> {
  322    266   
        // Trailers were already appended to the body because of the content encoding scheme
  323    267   
        Poll::Ready(Ok(None))
  324    268   
    }
  325    269   
  326    270   
    fn is_end_stream(&self) -> bool {
  327    271   
        self.state == AwsChunkedBodyState::Closed
  328    272   
    }
  329    273   
  330         -
    fn size_hint(&self) -> SizeHint {
  331         -
        SizeHint::with_exact(self.options.encoded_length())
         274  +
    fn size_hint(&self) -> http_body_04x::SizeHint {
         275  +
        http_body_04x::SizeHint::with_exact(self.options.encoded_length())
         276  +
    }
         277  +
}
         278  +
         279  +
/// Utility functions to help with the [http_body_04x::Body] trait implementation
         280  +
mod http_02x_utils {
         281  +
    use super::{CRLF, TRAILER_SEPARATOR};
         282  +
    use bytes::BytesMut;
         283  +
    use http_02x::HeaderMap;
         284  +
         285  +
    /// Writes trailers out into a `string` and then converts that `String` to a `Bytes` before
         286  +
    /// returning.
         287  +
    ///
         288  +
    /// - Trailer names are separated by a single colon only, no space.
         289  +
    /// - Trailer names with multiple values will be written out one line per value, with the name
         290  +
    ///   appearing on each line.
         291  +
    pub(super) fn trailers_as_aws_chunked_bytes(
         292  +
        trailer_map: Option<HeaderMap>,
         293  +
        estimated_length: u64,
         294  +
    ) -> BytesMut {
         295  +
        if let Some(trailer_map) = trailer_map {
         296  +
            let mut current_header_name = None;
         297  +
            let mut trailers =
         298  +
                BytesMut::with_capacity(estimated_length.try_into().unwrap_or_default());
         299  +
         300  +
            for (header_name, header_value) in trailer_map.into_iter() {
         301  +
                // When a header has multiple values, the name only comes up in iteration the first time
         302  +
                // we see it. Therefore, we need to keep track of the last name we saw and fall back to
         303  +
                // it when `header_name == None`.
         304  +
                current_header_name = header_name.or(current_header_name);
         305  +
         306  +
                // In practice, this will always exist, but `if let` is nicer than unwrap
         307  +
                if let Some(header_name) = current_header_name.as_ref() {
         308  +
                    trailers.extend_from_slice(header_name.as_ref());
         309  +
                    trailers.extend_from_slice(TRAILER_SEPARATOR);
         310  +
                    trailers.extend_from_slice(header_value.as_bytes());
         311  +
                    trailers.extend_from_slice(CRLF.as_bytes());
         312  +
                }
         313  +
            }
         314  +
         315  +
            trailers
         316  +
        } else {
         317  +
            BytesMut::new()
         318  +
        }
         319  +
    }
         320  +
         321  +
    /// Given an optional `HeaderMap`, calculate the total number of bytes required to represent the
         322  +
    /// `HeaderMap`. If no `HeaderMap` is given as input, return 0.
         323  +
    ///
         324  +
    /// - Trailer names are separated by a single colon only, no space.
         325  +
    /// - Trailer names with multiple values will be written out one line per value, with the name
         326  +
    ///   appearing on each line.
         327  +
    pub(super) fn total_rendered_length_of_trailers(trailer_map: Option<&HeaderMap>) -> u64 {
         328  +
        match trailer_map {
         329  +
            Some(trailer_map) => trailer_map
         330  +
                .iter()
         331  +
                .map(|(trailer_name, trailer_value)| {
         332  +
                    trailer_name.as_str().len()
         333  +
                        + TRAILER_SEPARATOR.len()
         334  +
                        + trailer_value.len()
         335  +
                        + CRLF.len()
         336  +
                })
         337  +
                .sum::<usize>() as u64,
         338  +
            None => 0,
         339  +
        }
         340  +
    }
         341  +
}
         342  +
         343  +
const UNREACHABLE_STATES: &str = "These states already short circuited";
         344  +
         345  +
/// Implementing the [http_body_1x::Body] trait
         346  +
impl<Inner> http_body_1x::Body for AwsChunkedBody<Inner>
         347  +
where
         348  +
    Inner: http_body_1x::Body<Data = Bytes, Error = aws_smithy_types::body::Error>,
         349  +
{
         350  +
    type Data = Bytes;
         351  +
    type Error = aws_smithy_types::body::Error;
         352  +
         353  +
    fn is_end_stream(&self) -> bool {
         354  +
        self.state == AwsChunkedBodyState::Closed
         355  +
    }
         356  +
         357  +
    fn size_hint(&self) -> http_body_1x::SizeHint {
         358  +
        http_body_1x::SizeHint::with_exact(self.options.encoded_length())
         359  +
    }
         360  +
         361  +
    fn poll_frame(
         362  +
        self: Pin<&mut Self>,
         363  +
        cx: &mut Context<'_>,
         364  +
    ) -> Poll<Option<Result<http_body_1x::Frame<Self::Data>, Self::Error>>> {
         365  +
        tracing::trace!(state = ?self.state, "polling AwsChunkedBody");
         366  +
        let mut this = self.project();
         367  +
         368  +
        // Both `WritingChunkSize` and `Closed` states short circuit without polling the inner body
         369  +
         370  +
        // Initial setup, we do not poll the inner body here
         371  +
        if *this.state == AwsChunkedBodyState::WritingChunkSize {
         372  +
            if this.options.stream_length == 0 {
         373  +
                // If the stream is empty, we skip to writing trailers after writing the CHUNK_TERMINATOR.
         374  +
                tracing::trace!("stream is empty, writing chunk terminator");
         375  +
                let frame = http_body_1x::Frame::data(Bytes::from(CHUNK_TERMINATOR));
         376  +
                *this.state = AwsChunkedBodyState::WritingTrailers;
         377  +
                return Poll::Ready(Some(Ok(frame)));
         378  +
            } else {
         379  +
                // A chunk must be prefixed by chunk size in hexadecimal
         380  +
                let chunk_size = format!(
         381  +
                    "{:X?}{}",
         382  +
                    this.options.stream_length,
         383  +
                    std::str::from_utf8(CRLF_RAW).unwrap()
         384  +
                );
         385  +
                tracing::trace!(%chunk_size, "writing chunk size");
         386  +
                let chunk_size = http_body_1x::Frame::data(Bytes::from(chunk_size));
         387  +
                *this.state = AwsChunkedBodyState::WritingChunk;
         388  +
                return Poll::Ready(Some(Ok(chunk_size)));
         389  +
            }
         390  +
        }
         391  +
         392  +
        // Polled after completion
         393  +
        if *this.state == AwsChunkedBodyState::Closed {
         394  +
            return Poll::Ready(None);
         395  +
        }
         396  +
         397  +
        // For all other states we must poll the inner body
         398  +
        let maybe_frame = this.inner.poll_frame(cx);
         399  +
        tracing::trace!(poll_state = ?maybe_frame, "Polling InnerBody");
         400  +
         401  +
        match maybe_frame {
         402  +
            Poll::Ready(Some(Ok(frame))) => match *this.state {
         403  +
                // Both data chunks and trailers are written as Frame::data so we treat these states similarly
         404  +
                // Importantly we cannot know that the body data of the InnerBody is exhausted until we see a
         405  +
                // trailer frame or a Poll::Ready(None)
         406  +
                AwsChunkedBodyState::WritingChunk => {
         407  +
                    if frame.is_data() {
         408  +
                        let data = frame.data_ref().expect("Data frame has data");
         409  +
                        tracing::trace!(len = data.len(), "Writing chunk data");
         410  +
                        *this.inner_body_bytes_read_so_far += data.len();
         411  +
                        Poll::Ready(Some(Ok(frame)))
         412  +
                    } else {
         413  +
                        tracing::trace!(
         414  +
                            "No more chunk data, writing CRLF + CHUNK_TERMINATOR to end the data, and the first trailer frame"
         415  +
                        );
         416  +
         417  +
                        // We exhausted the body data, now check if the length is correct
         418  +
                        if let Err(poll_stream_len_err) =
         419  +
                            http_1x_utils::check_for_stream_length_mismatch(
         420  +
                                *this.inner_body_bytes_read_so_far as u64,
         421  +
                                this.options.stream_length,
         422  +
                            )
         423  +
                        {
         424  +
                            return poll_stream_len_err;
         425  +
                        }
         426  +
         427  +
                        *this.state = AwsChunkedBodyState::WritingTrailers;
         428  +
                        let trailers = frame.trailers_ref();
         429  +
         430  +
                        // NOTE: there is a subtle logic bug here (which is present in the http-02x implementation as well)
         431  +
                        // The check for this error assumes that all trailers will come in a single trailer frame. Currently
         432  +
                        // I believe this will always be the case since the only thing we send trailers for in AwsChunked is
         433  +
                        // streaming checksums and that is a single trailer value. But it might not always be true. We should
         434  +
                        // fix this bug when we update the behavior here to match the actual spec.
         435  +
                        // The fix probably looks like returning Poll::Pending while we buffer all of the trailers and then
         436  +
                        // comparing the actual length to the expected length before returning a final frame containing all
         437  +
                        // of the trailers.
         438  +
                        let actual_length: u64 =
         439  +
                            http_1x_utils::total_rendered_length_of_trailers(trailers);
         440  +
                        let expected_length = this.options.total_trailer_length();
         441  +
                        if expected_length != actual_length {
         442  +
                            let err =
         443  +
                                Box::new(AwsChunkedBodyError::ReportedTrailerLengthMismatch {
         444  +
                                    actual: actual_length,
         445  +
                                    expected: expected_length,
         446  +
                                });
         447  +
                            return Poll::Ready(Some(Err(err)));
         448  +
                        }
         449  +
         450  +
                        // Capacity = actual_length (in case all of the trailers specified in  come in AwsChunkedBodyOptions
         451  +
                        // come in the first trailer frame which is going to be the case most of the time in practice) + 7
         452  +
                        // (2 + 3) for the initial CRLF + CHUNK_TERMINATOR to end the chunked data + 2 for the final CRLF
         453  +
                        // ending the trailers section.
         454  +
                        let mut buf = BytesMut::with_capacity(actual_length as usize + 7);
         455  +
                        // End the final data chunk
         456  +
                        buf.extend_from_slice(&[CRLF_RAW, CHUNK_TERMINATOR_RAW].concat());
         457  +
         458  +
                        // We transform the trailers into raw bytes. We can't write them with Frame::trailers
         459  +
                        // since we must include the CRLF + CHUNK_TERMINATOR that end the body and the CRLFs
         460  +
                        // after each trailer, so we write them as Frame::data
         461  +
                        let trailers = http_1x_utils::trailers_as_aws_chunked_bytes(trailers, buf);
         462  +
                        Poll::Ready(Some(Ok(http_body_1x::Frame::data(trailers.into()))))
         463  +
                    }
         464  +
                }
         465  +
                AwsChunkedBodyState::WritingTrailers => {
         466  +
                    let trailers = frame.trailers_ref();
         467  +
                    let actual_length: u64 =
         468  +
                        http_1x_utils::total_rendered_length_of_trailers(trailers);
         469  +
                    let buf = BytesMut::with_capacity(actual_length as usize + 7);
         470  +
                    let trailers = http_1x_utils::trailers_as_aws_chunked_bytes(trailers, buf);
         471  +
                    Poll::Ready(Some(Ok(http_body_1x::Frame::data(trailers.into()))))
         472  +
                }
         473  +
                AwsChunkedBodyState::Closed | AwsChunkedBodyState::WritingChunkSize => {
         474  +
                    unreachable!("{}", UNREACHABLE_STATES)
         475  +
                }
         476  +
            },
         477  +
            // InnerBody data exhausted, add finalizing bytes depending on current state
         478  +
            Poll::Ready(None) => {
         479  +
                let trailers = match *this.state {
         480  +
                    AwsChunkedBodyState::WritingChunk => {
         481  +
                        // We exhausted the body data, now check if the length is correct
         482  +
                        if let Err(poll_stream_len_err) =
         483  +
                            http_1x_utils::check_for_stream_length_mismatch(
         484  +
                                *this.inner_body_bytes_read_so_far as u64,
         485  +
                                this.options.stream_length,
         486  +
                            )
         487  +
                        {
         488  +
                            return poll_stream_len_err;
         489  +
                        }
         490  +
         491  +
                        // Since we exhausted the body data, but are still in the WritingChunk state we did
         492  +
                        // not poll any trailer frames and we write the CRLF + Chunk terminator to begin the
         493  +
                        // trailer section plus a single final CRLF to end the (empty) trailer section
         494  +
                        let mut trailers = BytesMut::with_capacity(7);
         495  +
                        trailers.extend_from_slice(
         496  +
                            &[CRLF_RAW, CHUNK_TERMINATOR_RAW, CRLF_RAW].concat(),
         497  +
                        );
         498  +
                        trailers
         499  +
                    }
         500  +
                    AwsChunkedBodyState::WritingTrailers => {
         501  +
                        let mut trailers = BytesMut::with_capacity(2);
         502  +
                        trailers.extend_from_slice(CRLF_RAW);
         503  +
                        trailers
         504  +
                    }
         505  +
                    AwsChunkedBodyState::Closed | AwsChunkedBodyState::WritingChunkSize => {
         506  +
                        unreachable!("{}", UNREACHABLE_STATES)
         507  +
                    }
         508  +
                };
         509  +
         510  +
                let frame = http_body_1x::Frame::data(trailers.into());
         511  +
                *this.state = AwsChunkedBodyState::Closed;
         512  +
                Poll::Ready(Some(Ok(frame)))
         513  +
            }
         514  +
            // Passthrough states
         515  +
            Poll::Pending => Poll::Pending,
         516  +
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
         517  +
        }
         518  +
    }
         519  +
}
         520  +
/// Utility functions to help with the [http_body_1x::Body] trait implementation
         521  +
mod http_1x_utils {
         522  +
    use std::task::Poll;
         523  +
         524  +
    use super::{CRLF_RAW, TRAILER_SEPARATOR};
         525  +
    use bytes::{Bytes, BytesMut};
         526  +
    use http_1x::{HeaderMap, HeaderName};
         527  +
         528  +
    /// Writes trailers out into a `string` and then converts that `String` to a `Bytes` before
         529  +
    /// returning.
         530  +
    ///
         531  +
    /// - Trailer names are separated by a single colon only, no space.
         532  +
    /// - Trailer names with multiple values will be written out one line per value, with the name
         533  +
    ///   appearing on each line.
         534  +
    pub(super) fn trailers_as_aws_chunked_bytes(
         535  +
        trailer_map: Option<&HeaderMap>,
         536  +
        mut buffer: BytesMut,
         537  +
    ) -> BytesMut {
         538  +
        if let Some(trailer_map) = trailer_map {
         539  +
            let mut current_header_name: Option<HeaderName> = None;
         540  +
         541  +
            for (header_name, header_value) in trailer_map.clone().into_iter() {
         542  +
                // When a header has multiple values, the name only comes up in iteration the first time
         543  +
                // we see it. Therefore, we need to keep track of the last name we saw and fall back to
         544  +
                // it when `header_name == None`.
         545  +
                current_header_name = header_name.or(current_header_name);
         546  +
         547  +
                // In practice, this will always exist, but `if let` is nicer than unwrap
         548  +
                if let Some(header_name) = current_header_name.as_ref() {
         549  +
                    buffer.extend_from_slice(header_name.as_ref());
         550  +
                    buffer.extend_from_slice(TRAILER_SEPARATOR);
         551  +
                    buffer.extend_from_slice(header_value.as_bytes());
         552  +
                    buffer.extend_from_slice(CRLF_RAW);
         553  +
                }
         554  +
            }
         555  +
         556  +
            buffer
         557  +
        } else {
         558  +
            buffer
         559  +
        }
         560  +
    }
         561  +
         562  +
    /// Given an optional `HeaderMap`, calculate the total number of bytes required to represent the
         563  +
    /// `HeaderMap`. If no `HeaderMap` is given as input, return 0.
         564  +
    ///
         565  +
    /// - Trailer names are separated by a single colon only, no space.
         566  +
    /// - Trailer names with multiple values will be written out one line per value, with the name
         567  +
    ///   appearing on each line.
         568  +
    pub(super) fn total_rendered_length_of_trailers(trailer_map: Option<&HeaderMap>) -> u64 {
         569  +
        match trailer_map {
         570  +
            Some(trailer_map) => trailer_map
         571  +
                .iter()
         572  +
                .map(|(trailer_name, trailer_value)| {
         573  +
                    trailer_name.as_str().len()
         574  +
                        + TRAILER_SEPARATOR.len()
         575  +
                        + trailer_value.len()
         576  +
                        + CRLF_RAW.len()
         577  +
                })
         578  +
                .sum::<usize>() as u64,
         579  +
            None => 0,
         580  +
        }
         581  +
    }
         582  +
         583  +
    /// This is an ugly return type, but in practice it just returns `Ok(())` if the values match
         584  +
    /// and `Err(Poll::Ready(Some(Err(AwsChunkedBodyError::StreamLengthMismatch))))` if they don't
         585  +
    #[allow(clippy::type_complexity)]
         586  +
    pub(super) fn check_for_stream_length_mismatch(
         587  +
        actual_stream_length: u64,
         588  +
        expected_stream_length: u64,
         589  +
    ) -> Result<(), Poll<Option<Result<http_body_1x::Frame<Bytes>, aws_smithy_types::body::Error>>>>
         590  +
    {
         591  +
        if actual_stream_length != expected_stream_length {
         592  +
            let err = Box::new(super::AwsChunkedBodyError::StreamLengthMismatch {
         593  +
                actual: actual_stream_length,
         594  +
                expected: expected_stream_length,
         595  +
            });
         596  +
            return Err(Poll::Ready(Some(Err(err))));
         597  +
        };
         598  +
         599  +
        Ok(())
  332    600   
    }
  333    601   
}
  334    602   
  335    603   
/// Errors related to `AwsChunkedBody`
  336    604   
#[derive(Debug)]
  337    605   
enum AwsChunkedBodyError {
  338    606   
    /// Error that occurs when the sum of `trailer_lengths` set when creating an `AwsChunkedBody` is
  339    607   
    /// not equal to the actual length of the trailers returned by the inner `http_body::Body`
  340    608   
    /// implementor. These trailer lengths are necessary in order to correctly calculate the total
  341    609   
    /// size of the body for setting the content length header.
  342    610   
    ReportedTrailerLengthMismatch { actual: u64, expected: u64 },
  343    611   
    /// Error that occurs when the `stream_length` set when creating an `AwsChunkedBody` is not
  344    612   
    /// equal to the actual length of the body returned by the inner `http_body::Body` implementor.
  345    613   
    /// `stream_length` must be correct in order to set an accurate content length header.
  346    614   
    StreamLengthMismatch { actual: u64, expected: u64 },
  347    615   
}
  348    616   
  349    617   
impl std::fmt::Display for AwsChunkedBodyError {
  350    618   
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  351    619   
        match self {
  352    620   
            Self::ReportedTrailerLengthMismatch { actual, expected } => {
  353    621   
                write!(f, "When creating this AwsChunkedBody, length of trailers was reported as {expected}. However, when double checking during trailer encoding, length was found to be {actual} instead.")
  354    622   
            }
  355    623   
            Self::StreamLengthMismatch { actual, expected } => {
  356    624   
                write!(f, "When creating this AwsChunkedBody, stream length was reported as {expected}. However, when double checking during body encoding, length was found to be {actual} instead.")
  357    625   
            }
  358    626   
        }
  359    627   
    }
  360    628   
}
  361    629   
  362    630   
impl std::error::Error for AwsChunkedBodyError {}
  363    631   
  364    632   
// Used for finding how many hexadecimal digits it takes to represent a base 10 integer
  365    633   
fn int_log16<T>(mut i: T) -> u64
  366    634   
where
  367    635   
    T: std::ops::DivAssign + PartialOrd + From<u8> + Copy,
  368    636   
{
  369    637   
    let mut len = 0;
  370    638   
    let zero = T::from(0);
  371    639   
    let sixteen = T::from(16);
  372    640   
  373    641   
    while i > zero {
  374    642   
        i /= sixteen;
  375    643   
        len += 1;
  376    644   
    }
  377    645   
  378    646   
    len
  379    647   
}
  380    648   
         649  +
fn get_unsigned_chunk_bytes_length(payload_length: u64) -> u64 {
         650  +
    let hex_repr_len = int_log16(payload_length);
         651  +
    hex_repr_len + CRLF.len() as u64 + payload_length + CRLF.len() as u64
         652  +
}
         653  +
  381    654   
#[cfg(test)]
  382    655   
mod tests {
  383         -
    use super::{
  384         -
        total_rendered_length_of_trailers, trailers_as_aws_chunked_bytes, AwsChunkedBody,
  385         -
        AwsChunkedBodyOptions, CHUNK_TERMINATOR, CRLF,
         656  +
         657  +
    #[cfg(test)]
         658  +
    mod http_02x_tests {
         659  +
        use super::super::{
         660  +
            http_02x_utils::{total_rendered_length_of_trailers, trailers_as_aws_chunked_bytes},
         661  +
            AwsChunkedBody, AwsChunkedBodyOptions, CHUNK_TERMINATOR, CRLF,
  386    662   
        };
  387    663   
  388    664   
        use aws_smithy_types::body::SdkBody;
  389    665   
        use bytes::{Buf, Bytes};
  390    666   
        use bytes_utils::SegmentedBuf;
  391    667   
        use http_02x::{HeaderMap, HeaderValue};
  392    668   
        use http_body_04x::{Body, SizeHint};
  393    669   
        use pin_project_lite::pin_project;
  394    670   
  395    671   
        use std::io::Read;
@@ -601,877 +644,1158 @@
  621    897   
  622    898   
            trailers.insert("two_values", HeaderValue::from_static("value 1"));
  623    899   
            trailers.append("two_values", HeaderValue::from_static("value 2"));
  624    900   
  625    901   
            trailers.insert("three_values", HeaderValue::from_static("value 1"));
  626    902   
            trailers.append("three_values", HeaderValue::from_static("value 2"));
  627    903   
            trailers.append("three_values", HeaderValue::from_static("value 3"));
  628    904   
  629    905   
            let trailers = Some(trailers);
  630    906   
            let actual_length = total_rendered_length_of_trailers(trailers.as_ref());
  631         -
        let expected_length = (trailers_as_aws_chunked_bytes(trailers, actual_length).len()) as u64;
         907  +
            let expected_length =
         908  +
                (trailers_as_aws_chunked_bytes(trailers, actual_length).len()) as u64;
  632    909   
  633    910   
            assert_eq!(expected_length, actual_length);
  634    911   
        }
  635    912   
  636    913   
        #[tokio::test]
  637    914   
        async fn test_total_rendered_length_of_empty_trailers() {
  638    915   
            let trailers = Some(HeaderMap::new());
  639    916   
            let actual_length = total_rendered_length_of_trailers(trailers.as_ref());
  640         -
        let expected_length = (trailers_as_aws_chunked_bytes(trailers, actual_length).len()) as u64;
         917  +
            let expected_length =
         918  +
                (trailers_as_aws_chunked_bytes(trailers, actual_length).len()) as u64;
         919  +
         920  +
            assert_eq!(expected_length, actual_length);
         921  +
        }
         922  +
    }
         923  +
         924  +
    #[cfg(test)]
         925  +
    mod http_1x_tests {
         926  +
        use super::super::{
         927  +
            http_1x_utils::{total_rendered_length_of_trailers, trailers_as_aws_chunked_bytes},
         928  +
            AwsChunkedBody, AwsChunkedBodyOptions, CHUNK_TERMINATOR_RAW, CRLF_RAW,
         929  +
        };
         930  +
         931  +
        use aws_smithy_types::body::SdkBody;
         932  +
        use bytes::{Buf, Bytes, BytesMut};
         933  +
        use bytes_utils::SegmentedBuf;
         934  +
        use http_1x::{HeaderMap, HeaderValue};
         935  +
        use http_body_1x::{Body, Frame, SizeHint};
         936  +
        use http_body_util::BodyExt;
         937  +
        use pin_project_lite::pin_project;
         938  +
         939  +
        use std::io::Read;
         940  +
        use std::pin::Pin;
         941  +
        use std::task::{Context, Poll};
         942  +
        use std::time::Duration;
         943  +
         944  +
        pin_project! {
         945  +
            struct SputteringBody {
         946  +
                parts: Vec<Option<Bytes>>,
         947  +
                cursor: usize,
         948  +
                delay_in_millis: u64,
         949  +
            }
         950  +
        }
         951  +
         952  +
        impl SputteringBody {
         953  +
            fn len(&self) -> usize {
         954  +
                self.parts.iter().flatten().map(|b| b.len()).sum()
         955  +
            }
         956  +
        }
         957  +
         958  +
        impl Body for SputteringBody {
         959  +
            type Data = Bytes;
         960  +
            type Error = aws_smithy_types::body::Error;
         961  +
         962  +
            fn poll_frame(
         963  +
                self: Pin<&mut Self>,
         964  +
                cx: &mut Context<'_>,
         965  +
            ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
         966  +
                if self.cursor == self.parts.len() {
         967  +
                    return Poll::Ready(None);
         968  +
                }
         969  +
         970  +
                let this = self.project();
         971  +
                let delay_in_millis = *this.delay_in_millis;
         972  +
                let next_part = this.parts.get_mut(*this.cursor).unwrap().take();
         973  +
         974  +
                match next_part {
         975  +
                    None => {
         976  +
                        *this.cursor += 1;
         977  +
                        let waker = cx.waker().clone();
         978  +
                        tokio::spawn(async move {
         979  +
                            tokio::time::sleep(Duration::from_millis(delay_in_millis)).await;
         980  +
                            waker.wake();
         981  +
                        });
         982  +
                        Poll::Pending
         983  +
                    }
         984  +
                    Some(data) => {
         985  +
                        *this.cursor += 1;
         986  +
                        let frame = Frame::data(data);
         987  +
                        Poll::Ready(Some(Ok(frame)))
         988  +
                    }
         989  +
                }
         990  +
            }
         991  +
         992  +
            fn is_end_stream(&self) -> bool {
         993  +
                false
         994  +
            }
         995  +
         996  +
            fn size_hint(&self) -> SizeHint {
         997  +
                SizeHint::new()
         998  +
            }
         999  +
        }
        1000  +
        1001  +
        #[tokio::test]
        1002  +
        async fn test_aws_chunked_encoding() {
        1003  +
            let test_fut = async {
        1004  +
                let input_str = "Hello world";
        1005  +
                let opts = AwsChunkedBodyOptions::new(input_str.len() as u64, vec![]);
        1006  +
                let mut body = AwsChunkedBody::new(SdkBody::from(input_str), opts);
        1007  +
        1008  +
                let mut output = SegmentedBuf::new();
        1009  +
                while let Some(Ok(buf)) = body.frame().await {
        1010  +
                    output.push(buf.into_data().unwrap());
        1011  +
                }
        1012  +
        1013  +
                let mut actual_output = String::new();
        1014  +
                output
        1015  +
                    .reader()
        1016  +
                    .read_to_string(&mut actual_output)
        1017  +
                    .expect("Doesn't cause IO errors");
        1018  +
        1019  +
                let expected_output = "B\r\nHello world\r\n0\r\n\r\n";
        1020  +
        1021  +
                assert_eq!(expected_output, actual_output);
        1022  +
        1023  +
                // You can insert a `tokio::time::sleep` here to verify the timeout works as intended
        1024  +
            };
        1025  +
        1026  +
            let timeout_duration = Duration::from_secs(3);
        1027  +
            if tokio::time::timeout(timeout_duration, test_fut)
        1028  +
                .await
        1029  +
                .is_err()
        1030  +
            {
        1031  +
                panic!("test_aws_chunked_encoding timed out after {timeout_duration:?}");
        1032  +
            }
        1033  +
        }
        1034  +
        1035  +
        #[tokio::test]
        1036  +
        async fn test_aws_chunked_encoding_sputtering_body() {
        1037  +
            let test_fut = async {
        1038  +
                let input = SputteringBody {
        1039  +
                    parts: vec![
        1040  +
                        Some(Bytes::from_static(b"chunk 1, ")),
        1041  +
                        None,
        1042  +
                        Some(Bytes::from_static(b"chunk 2, ")),
        1043  +
                        Some(Bytes::from_static(b"chunk 3, ")),
        1044  +
                        None,
        1045  +
                        None,
        1046  +
                        Some(Bytes::from_static(b"chunk 4, ")),
        1047  +
                        Some(Bytes::from_static(b"chunk 5, ")),
        1048  +
                        Some(Bytes::from_static(b"chunk 6")),
        1049  +
                    ],
        1050  +
                    cursor: 0,
        1051  +
                    delay_in_millis: 500,
        1052  +
                };
        1053  +
                let opts = AwsChunkedBodyOptions::new(input.len() as u64, vec![]);
        1054  +
                let mut body = AwsChunkedBody::new(input, opts);
        1055  +
        1056  +
                let mut output = SegmentedBuf::new();
        1057  +
                while let Some(Ok(buf)) = body.frame().await {
        1058  +
                    output.push(buf.into_data().unwrap());
        1059  +
                }
        1060  +
        1061  +
                let mut actual_output = String::new();
        1062  +
                output
        1063  +
                    .reader()
        1064  +
                    .read_to_string(&mut actual_output)
        1065  +
                    .expect("Doesn't cause IO errors");
        1066  +
        1067  +
                let expected_output =
        1068  +
                    "34\r\nchunk 1, chunk 2, chunk 3, chunk 4, chunk 5, chunk 6\r\n0\r\n\r\n";
        1069  +
        1070  +
                assert_eq!(expected_output, actual_output);
        1071  +
            };
        1072  +
        1073  +
            let timeout_duration = Duration::from_secs(3);
        1074  +
            if tokio::time::timeout(timeout_duration, test_fut)
        1075  +
                .await
        1076  +
                .is_err()
        1077  +
            {
        1078  +
                panic!(
        1079  +
                "test_aws_chunked_encoding_sputtering_body timed out after {timeout_duration:?}"
        1080  +
            );
        1081  +
            }
        1082  +
        }
        1083  +
        1084  +
        #[tokio::test]
        1085  +
        async fn test_aws_chunked_encoding_incorrect_trailer_length_panic() {
        1086  +
            let input_str = "Hello world";
        1087  +
            // Test body has no trailers, so this length is incorrect and will trigger an assert panic
        1088  +
            // When the panic occurs, it will actually expect a length of 44. This is because, when using
        1089  +
            // aws-chunked encoding, each trailer will end with a CRLF which is 2 bytes long.
        1090  +
            let wrong_trailer_len = 42;
        1091  +
            let opts = AwsChunkedBodyOptions::new(input_str.len() as u64, vec![wrong_trailer_len]);
        1092  +
            let mut body = AwsChunkedBody::new(SdkBody::from(input_str), opts);
        1093  +
        1094  +
            // We don't care about the body contents but we have to read it all before checking for trailers
        1095  +
            while let Some(Ok(frame)) = body.frame().await {
        1096  +
                assert!(!frame.is_trailers());
        1097  +
            }
        1098  +
        }
        1099  +
        1100  +
        #[tokio::test]
        1101  +
        async fn test_aws_chunked_encoding_empty_body() {
        1102  +
            let input_str = "";
        1103  +
            let opts = AwsChunkedBodyOptions::new(input_str.len() as u64, vec![]);
        1104  +
            let mut body = AwsChunkedBody::new(SdkBody::from(input_str), opts);
        1105  +
        1106  +
            let mut output = SegmentedBuf::new();
        1107  +
            while let Some(Ok(frame)) = body.frame().await {
        1108  +
                output.push(frame.into_data().unwrap());
        1109  +
            }
        1110  +
        1111  +
            let mut actual_output = String::new();
        1112  +
            output
        1113  +
                .reader()
        1114  +
                .read_to_string(&mut actual_output)
        1115  +
                .expect("Doesn't cause IO errors");
        1116  +
        1117  +
            let actual_output = std::str::from_utf8(actual_output.as_bytes()).unwrap();
        1118  +
            let expected_output = [CHUNK_TERMINATOR_RAW, CRLF_RAW].concat();
        1119  +
            let expected_output = std::str::from_utf8(&expected_output).unwrap();
        1120  +
        1121  +
            assert_eq!(expected_output, actual_output);
        1122  +
        }
        1123  +
        1124  +
        #[tokio::test]
        1125  +
        async fn test_total_rendered_length_of_trailers() {
        1126  +
            let mut trailers = HeaderMap::new();
        1127  +
        1128  +
            trailers.insert("empty_value", HeaderValue::from_static(""));
        1129  +
        1130  +
            trailers.insert("single_value", HeaderValue::from_static("value 1"));
        1131  +
        1132  +
            trailers.insert("two_values", HeaderValue::from_static("value 1"));
        1133  +
            trailers.append("two_values", HeaderValue::from_static("value 2"));
        1134  +
        1135  +
            trailers.insert("three_values", HeaderValue::from_static("value 1"));
        1136  +
            trailers.append("three_values", HeaderValue::from_static("value 2"));
        1137  +
            trailers.append("three_values", HeaderValue::from_static("value 3"));
        1138  +
        1139  +
            let trailers = Some(&trailers);
        1140  +
            let actual_length = total_rendered_length_of_trailers(trailers);
        1141  +
            let buf = BytesMut::with_capacity(actual_length as usize);
        1142  +
            let expected_length = (trailers_as_aws_chunked_bytes(trailers, buf).len()) as u64;
  641   1143   
  642   1144   
            assert_eq!(expected_length, actual_length);
  643   1145   
        }
        1146  +
        1147  +
        #[tokio::test]
        1148  +
        async fn test_total_rendered_length_of_empty_trailers() {
        1149  +
            let header_map = HeaderMap::new();
        1150  +
            let trailers = Some(&header_map);
        1151  +
            let actual_length = total_rendered_length_of_trailers(trailers);
        1152  +
            let buf = BytesMut::with_capacity(actual_length as usize);
        1153  +
            let expected_length = (trailers_as_aws_chunked_bytes(trailers, buf).len()) as u64;
        1154  +
        1155  +
            assert_eq!(expected_length, actual_length);
        1156  +
        }
        1157  +
    }
  644   1158   
}

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/invocation_id.rs

@@ -1,1 +40,40 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use std::fmt::Debug;
    7      7   
use std::sync::{Arc, Mutex};
    8      8   
    9      9   
use fastrand::Rng;
   10         -
use http_02x::{HeaderName, HeaderValue};
          10  +
use http_1x::{HeaderName, HeaderValue};
   11     11   
   12     12   
use aws_smithy_runtime_api::box_error::BoxError;
   13     13   
use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut;
   14     14   
use aws_smithy_runtime_api::client::interceptors::Intercept;
   15     15   
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
   16     16   
use aws_smithy_types::config_bag::{ConfigBag, Storable, StoreReplace};
   17     17   
#[cfg(feature = "test-util")]
   18     18   
pub use test_util::{NoInvocationIdGenerator, PredefinedInvocationIdGenerator};
   19     19   
   20     20   
#[allow(clippy::declare_interior_mutable_const)] // we will never mutate this

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/lib.rs

@@ -1,1 +53,52 @@
   12     12   
    missing_docs,
   13     13   
    rustdoc::missing_crate_level_docs,
   14     14   
    missing_debug_implementations,
   15     15   
    rust_2018_idioms,
   16     16   
    unreachable_pub
   17     17   
)]
   18     18   
   19     19   
/// Supporting code for authentication in the AWS SDK.
   20     20   
pub mod auth;
   21     21   
   22         -
/// AWS-specific content-encoding tools
   23         -
#[cfg(feature = "http-02x")]
          22  +
/// AWS-specific content-encoding tools for http-02x and http-1x
   24     23   
pub mod content_encoding;
   25     24   
   26     25   
/// Supporting code for recursion detection in the AWS SDK.
   27     26   
pub mod recursion_detection;
   28     27   
   29     28   
/// Supporting code for user agent headers in the AWS SDK.
   30     29   
pub mod user_agent;
   31     30   
   32     31   
/// Supporting code for retry behavior specific to the AWS SDK.
   33     32   
pub mod retries;

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/recursion_detection.rs

@@ -1,1 +42,42 @@
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use aws_smithy_runtime_api::box_error::BoxError;
    7      7   
use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut;
    8      8   
use aws_smithy_runtime_api::client::interceptors::Intercept;
    9      9   
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
   10     10   
use aws_smithy_types::config_bag::ConfigBag;
   11     11   
use aws_types::os_shim_internal::Env;
   12         -
use http_02x::HeaderValue;
          12  +
use http_1x::HeaderValue;
   13     13   
use percent_encoding::{percent_encode, CONTROLS};
   14     14   
use std::borrow::Cow;
   15     15   
   16     16   
const TRACE_ID_HEADER: &str = "x-amzn-trace-id";
   17     17   
   18     18   
mod env {
   19     19   
    pub(super) const LAMBDA_FUNCTION_NAME: &str = "AWS_LAMBDA_FUNCTION_NAME";
   20     20   
    pub(super) const TRACE_ID: &str = "_X_AMZN_TRACE_ID";
   21     21   
}
   22     22   
@@ -56,56 +116,116 @@
   76     76   
}
   77     77   
   78     78   
#[cfg(test)]
   79     79   
mod tests {
   80     80   
    use super::*;
   81     81   
    use aws_smithy_protocol_test::{assert_ok, validate_headers};
   82     82   
    use aws_smithy_runtime_api::client::interceptors::context::{Input, InterceptorContext};
   83     83   
    use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
   84     84   
    use aws_smithy_types::body::SdkBody;
   85     85   
    use aws_types::os_shim_internal::Env;
   86         -
    use http_02x::HeaderValue;
          86  +
    use http_1x::HeaderValue;
   87     87   
    use proptest::{prelude::*, proptest};
   88     88   
    use serde::Deserialize;
   89     89   
    use std::collections::HashMap;
   90     90   
   91     91   
    proptest! {
   92     92   
        #[test]
   93     93   
        fn header_encoding_never_panics(s in any::<Vec<u8>>()) {
   94     94   
            encode_header(&s);
   95     95   
        }
   96     96   
    }
@@ -123,123 +183,183 @@
  143    143   
        fn split_headers(headers: &[String]) -> impl Iterator<Item = (&str, &str)> {
  144    144   
            headers
  145    145   
                .iter()
  146    146   
                .map(|header| header.split_once(": ").expect("header must contain :"))
  147    147   
        }
  148    148   
    }
  149    149   
  150    150   
    fn check(test_case: TestCase) {
  151    151   
        let rc = RuntimeComponentsBuilder::for_tests().build().unwrap();
  152    152   
        let env = test_case.env();
  153         -
        let mut request = http_02x::Request::builder();
         153  +
        let mut request = http_1x::Request::builder();
  154    154   
        for (name, value) in test_case.request_headers_before() {
  155    155   
            request = request.header(name, value);
  156    156   
        }
  157    157   
        let request = request
  158    158   
            .body(SdkBody::empty())
  159    159   
            .expect("must be valid")
  160    160   
            .try_into()
  161    161   
            .unwrap();
  162    162   
        let mut context = InterceptorContext::new(Input::doesnt_matter());
  163    163   
        context.enter_serialization_phase();

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/request_info.rs

@@ -1,1 +48,48 @@
    8      8   
use aws_smithy_runtime_api::box_error::BoxError;
    9      9   
use aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut;
   10     10   
use aws_smithy_runtime_api::client::interceptors::Intercept;
   11     11   
use aws_smithy_runtime_api::client::retries::RequestAttempts;
   12     12   
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;
   13     13   
use aws_smithy_types::config_bag::ConfigBag;
   14     14   
use aws_smithy_types::date_time::Format;
   15     15   
use aws_smithy_types::retry::RetryConfig;
   16     16   
use aws_smithy_types::timeout::TimeoutConfig;
   17     17   
use aws_smithy_types::DateTime;
   18         -
use http_02x::{HeaderName, HeaderValue};
          18  +
use http_1x::{HeaderName, HeaderValue};
   19     19   
use std::borrow::Cow;
   20     20   
use std::time::Duration;
   21     21   
   22     22   
#[allow(clippy::declare_interior_mutable_const)] // we will never mutate this
   23     23   
const AMZ_SDK_REQUEST: HeaderName = HeaderName::from_static("amz-sdk-request");
   24     24   
   25     25   
/// Generates and attaches a request header that communicates request-related metadata.
   26     26   
/// Examples include:
   27     27   
///
   28     28   
/// - When the client will time out this request.
@@ -161,161 +221,221 @@
  181    181   
    use crate::request_info::RequestPairs;
  182    182   
    use aws_smithy_runtime_api::client::interceptors::context::Input;
  183    183   
    use aws_smithy_runtime_api::client::interceptors::context::InterceptorContext;
  184    184   
    use aws_smithy_runtime_api::client::interceptors::Intercept;
  185    185   
    use aws_smithy_runtime_api::client::orchestrator::HttpRequest;
  186    186   
    use aws_smithy_runtime_api::client::runtime_components::RuntimeComponentsBuilder;
  187    187   
    use aws_smithy_types::config_bag::{ConfigBag, Layer};
  188    188   
    use aws_smithy_types::retry::RetryConfig;
  189    189   
    use aws_smithy_types::timeout::TimeoutConfig;
  190    190   
  191         -
    use http_02x::HeaderValue;
         191  +
    use http_1x::HeaderValue;
  192    192   
    use std::time::Duration;
  193    193   
  194    194   
    fn expect_header<'a>(context: &'a InterceptorContext, header_name: &str) -> &'a str {
  195    195   
        context
  196    196   
            .request()
  197    197   
            .expect("request is set")
  198    198   
            .headers()
  199    199   
            .get(header_name)
  200    200   
            .unwrap()
  201    201   
    }

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/retries/classifiers.rs

@@ -189,189 +249,249 @@
  209    209   
        ctx.set_output_or_error(Err(OrchestratorError::operation(Error::erase(
  210    210   
            CodedError::new("RequestTimeout"),
  211    211   
        ))));
  212    212   
        assert_eq!(policy.classify_retry(&ctx), RetryAction::transient_error())
  213    213   
    }
  214    214   
  215    215   
    #[test]
  216    216   
    fn classify_generic() {
  217    217   
        let policy = AwsErrorCodeClassifier::<ErrorMetadata>::new();
  218    218   
        let err = ErrorMetadata::builder().code("SlowDown").build();
  219         -
        let test_response = http_02x::Response::new("OK").map(SdkBody::from);
         219  +
        let test_response = http_1x::Response::new("OK").map(SdkBody::from);
  220    220   
  221    221   
        let mut ctx = InterceptorContext::new(Input::doesnt_matter());
  222    222   
        ctx.set_response(test_response.try_into().unwrap());
  223    223   
        ctx.set_output_or_error(Err(OrchestratorError::operation(Error::erase(err))));
  224    224   
  225    225   
        assert_eq!(policy.classify_retry(&ctx), RetryAction::throttling_error());
  226    226   
    }
  227    227   
  228    228   
    #[test]
  229    229   
    fn test_retry_after_header() {
  230    230   
        let policy = AwsErrorCodeClassifier::<ErrorMetadata>::new();
  231    231   
        let err = ErrorMetadata::builder().code("SlowDown").build();
  232         -
        let res = http_02x::Response::builder()
         232  +
        let res = http_1x::Response::builder()
  233    233   
            .header("x-amz-retry-after", "5000")
  234    234   
            .body("retry later")
  235    235   
            .unwrap()
  236    236   
            .map(SdkBody::from);
  237    237   
        let mut ctx = InterceptorContext::new(Input::doesnt_matter());
  238    238   
        ctx.set_response(res.try_into().unwrap());
  239    239   
        ctx.set_output_or_error(Err(OrchestratorError::operation(Error::erase(err))));
  240    240   
  241    241   
        assert_eq!(
  242    242   
            policy.classify_retry(&ctx),

tmp-codegen-diff/aws-sdk/sdk/aws-runtime/src/user_agent/interceptor.rs

@@ -1,1 +39,39 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6      6   
use std::borrow::Cow;
    7      7   
use std::fmt;
    8      8   
    9         -
use http_02x::header::{HeaderName, HeaderValue, InvalidHeaderValue, USER_AGENT};
           9  +
use http_1x::header::{HeaderName, HeaderValue, InvalidHeaderValue, USER_AGENT};
   10     10   
   11     11   
use aws_credential_types::credential_feature::AwsCredentialFeature;
   12     12   
use aws_smithy_runtime::client::sdk_feature::SmithySdkFeature;
   13     13   
use aws_smithy_runtime_api::box_error::BoxError;
   14     14   
use aws_smithy_runtime_api::client::http::HttpClient;
   15     15   
use aws_smithy_runtime_api::client::interceptors::context::{
   16     16   
    BeforeTransmitInterceptorContextMut, BeforeTransmitInterceptorContextRef,
   17     17   
};
   18     18   
use aws_smithy_runtime_api::client::interceptors::Intercept;
   19     19   
use aws_smithy_runtime_api::client::runtime_components::RuntimeComponents;

tmp-codegen-diff/aws-sdk/sdk/aws-sigv4/Cargo.toml

@@ -1,1 +131,131 @@
    3      3   
name = "hmac"
    4      4   
harness = false
    5      5   
    6      6   
[[bench]]
    7      7   
name = "sigv4a"
    8      8   
harness = false
    9      9   
required-features = ["sigv4a"]
   10     10   
   11     11   
[package]
   12     12   
name = "aws-sigv4"
   13         -
version = "1.3.7"
          13  +
version = "1.3.8"
   14     14   
authors = ["AWS Rust SDK Team <aws-sdk-rust@amazon.com>", "David Barsky <me@davidbarsky.com>"]
   15     15   
description = "SigV4 signer for HTTP requests and Event Stream messages."
   16     16   
edition = "2021"
   17     17   
exclude = ["aws-sig-v4-test-suite/*"]
   18     18   
license = "Apache-2.0"
   19     19   
repository = "https://github.com/smithy-lang/smithy-rs"
   20     20   
rust-version = "1.88"
   21     21   
[package.metadata.docs.rs]
   22     22   
all-features = true
   23     23   
targets = ["x86_64-unknown-linux-gnu"]
   24     24   
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
   25     25   
rustdoc-args = ["--cfg", "docsrs"]
   26     26   
   27     27   
[package.metadata.smithy-rs-release-tooling]
   28     28   
stable = true
   29     29   
   30     30   
[features]
   31     31   
default = ["sign-http", "http1"]
   32     32   
http0-compat = ["dep:http0"]
   33     33   
http1 = ["dep:http"]
   34     34   
sign-http = ["dep:http0", "dep:percent-encoding", "dep:form_urlencoded"]
   35     35   
sign-eventstream = ["dep:aws-smithy-eventstream"]
   36     36   
sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:subtle", "dep:zeroize", "dep:ring"]
   37     37   
   38     38   
[dependencies]
   39     39   
bytes = "1.10.0"
   40     40   
hex = "0.4.3"
   41     41   
hmac = "0.12"
   42     42   
sha2 = "0.10"
   43     43   
time = "0.3.5"
   44     44   
tracing = "0.1.40"
   45     45   
   46     46   
[dependencies.aws-credential-types]
   47     47   
path = "../aws-credential-types"
   48     48   
version = "1.2.11"
   49     49   
   50     50   
[dependencies.aws-smithy-eventstream]
   51     51   
path = "../aws-smithy-eventstream"
   52     52   
optional = true
   53         -
version = "0.60.14"
          53  +
version = "0.60.15"
   54     54   
   55     55   
[dependencies.aws-smithy-http]
   56     56   
path = "../aws-smithy-http"
   57         -
version = "0.62.6"
          57  +
version = "0.63.0"
   58     58   
   59     59   
[dependencies.aws-smithy-runtime-api]
   60     60   
path = "../aws-smithy-runtime-api"
   61     61   
features = ["client"]
   62         -
version = "1.10.0"
          62  +
version = "1.11.0"
   63     63   
   64     64   
[dependencies.aws-smithy-types]
   65     65   
path = "../aws-smithy-types"
   66         -
version = "1.3.6"
          66  +
version = "1.4.0"
   67     67   
   68     68   
[dependencies.form_urlencoded]
   69     69   
version = "1.2.1"
   70     70   
optional = true
   71     71   
   72     72   
[dependencies.http0]
   73         -
version = "0.2.9"
   74         -
optional = true
   75     73   
package = "http"
          74  +
version = "0.2.12"
          75  +
optional = true
   76     76   
   77     77   
[dependencies.http]
   78         -
version = "1.1.0"
          78  +
version = "1.3.1"
   79     79   
optional = true
   80     80   
   81     81   
[dependencies.p256]
   82     82   
version = "0.11"
   83     83   
features = ["ecdsa"]
   84     84   
optional = true
   85     85   
   86     86   
[dependencies.percent-encoding]
   87     87   
version = "2.3.1"
   88     88   
optional = true
   89     89   
   90     90   
[dependencies.ring]
   91     91   
version = "0.17.5"
   92     92   
optional = true
   93     93   
   94     94   
[dependencies.crypto-bigint]
   95     95   
version = "0.5.4"
   96     96   
optional = true
   97     97   
   98     98   
[dependencies.subtle]
   99     99   
version = "2.5.0"
  100    100   
optional = true
  101    101   
  102    102   
[dependencies.zeroize]
  103    103   
version = "^1.7.0"
  104    104   
optional = true
  105    105   
  106    106   
[dev-dependencies]
  107    107   
bytes = "1"
  108    108   
hex-literal = "0.4.1"
  109    109   
httparse = "1.10.1"
  110    110   
pretty_assertions = "1.3"
  111    111   
proptest = "1.2"
  112    112   
serde = "1.0.180"
  113    113   
serde_derive = "1.0.180"
  114    114   
serde_json = "1.0.104"
  115    115   
criterion = "0.5"
  116    116   
  117    117   
[dev-dependencies.aws-credential-types]
  118    118   
path = "../aws-credential-types"
  119    119   
features = ["test-util", "hardcoded-credentials"]
  120    120   
version = "1.2.11"
  121    121   
  122    122   
[dev-dependencies.aws-smithy-runtime-api]
  123    123   
path = "../aws-smithy-runtime-api"
  124    124   
features = ["client", "test-util"]
  125         -
version = "1.10.0"
         125  +
version = "1.11.0"
  126    126   
  127    127   
[dev-dependencies.time]
  128    128   
version = "0.3.5"
  129    129   
features = ["parsing"]
  130    130   
[target."cfg(not(any(target_arch = \"powerpc\", target_arch = \"powerpc64\")))".dev-dependencies]
  131    131   
ring = "0.17.5"

tmp-codegen-diff/aws-sdk/sdk/aws-sigv4/src/http_request/canonical_request.rs

@@ -1,1 +50,50 @@
    8      8   
use crate::http_request::settings::SessionTokenMode;
    9      9   
use crate::http_request::settings::UriPathNormalizationMode;
   10     10   
use crate::http_request::sign::SignableRequest;
   11     11   
use crate::http_request::uri_path_normalization::normalize_uri_path;
   12     12   
use crate::http_request::url_escape::percent_encode_path;
   13     13   
use crate::http_request::{PayloadChecksumKind, SignableBody, SignatureLocation, SigningParams};
   14     14   
use crate::http_request::{PercentEncodingMode, SigningSettings};
   15     15   
use crate::sign::v4::sha256_hex_string;
   16     16   
use crate::SignatureVersion;
   17     17   
use aws_smithy_http::query_writer::QueryWriter;
   18         -
use http0::header::{AsHeaderName, HeaderName, HOST};
   19         -
use http0::uri::{Port, Scheme};
   20         -
use http0::{HeaderMap, HeaderValue, Uri};
          18  +
use http::header::{AsHeaderName, HeaderName, HOST};
          19  +
use http::uri::{Port, Scheme};
          20  +
use http::{HeaderMap, HeaderValue, Uri};
   21     21   
use std::borrow::Cow;
   22     22   
use std::cmp::Ordering;
   23     23   
use std::fmt;
   24     24   
use std::str::FromStr;
   25     25   
use std::time::SystemTime;
   26     26   
   27     27   
#[cfg(feature = "sigv4a")]
   28     28   
pub(crate) mod sigv4a;
   29     29   
   30     30   
pub(crate) mod header {
@@ -663,663 +723,723 @@
  683    683   
    use crate::http_request::test::SigningSuiteTest;
  684    684   
    use crate::http_request::{
  685    685   
        PayloadChecksumKind, SessionTokenMode, SignableBody, SignableRequest, SignatureLocation,
  686    686   
        SigningParams, SigningSettings,
  687    687   
    };
  688    688   
    use crate::sign::v4;
  689    689   
    use crate::sign::v4::sha256_hex_string;
  690    690   
    use aws_credential_types::Credentials;
  691    691   
    use aws_smithy_http::query_writer::QueryWriter;
  692    692   
    use aws_smithy_runtime_api::client::identity::Identity;
  693         -
    use http0::{HeaderValue, Uri};
         693  +
    use http::{HeaderValue, Uri};
  694    694   
    use pretty_assertions::assert_eq;
  695    695   
    use proptest::{prelude::*, proptest};
  696    696   
    use std::borrow::Cow;
  697    697   
    use std::time::Duration;
  698    698   
  699    699   
    fn signing_params(identity: &Identity, settings: SigningSettings) -> SigningParams<'_> {
  700    700   
        v4::signing_params::Builder::default()
  701    701   
            .identity(identity)
  702    702   
            .region("test-region")
  703    703   
            .name("testservicename")
@@ -873,873 +1086,1086 @@
  893    893   
        let identity = Credentials::for_tests().into();
  894    894   
        let signing_params = signing_params(&identity, SigningSettings::default());
  895    895   
        let creq = CanonicalRequest::from(&req, &signing_params).unwrap();
  896    896   
        let expected = test.canonical_request(SignatureLocation::Headers);
  897    897   
        let actual = format!("{}", creq);
  898    898   
        assert_eq!(actual, expected);
  899    899   
    }
  900    900   
  901    901   
    #[test]
  902    902   
    fn test_tilde_in_uri() {
  903         -
        let req = http0::Request::builder()
         903  +
        let req = http::Request::builder()
  904    904   
            .uri("https://s3.us-east-1.amazonaws.com/my-bucket?list-type=2&prefix=~objprefix&single&k=&unreserved=-_.~").body("").unwrap().into();
  905    905   
        let req = SignableRequest::from(&req);
  906    906   
        let identity = Credentials::for_tests().into();
  907    907   
        let signing_params = signing_params(&identity, SigningSettings::default());
  908    908   
        let creq = CanonicalRequest::from(&req, &signing_params).unwrap();
  909    909   
        assert_eq!(
  910    910   
            Some("k=&list-type=2&prefix=~objprefix&single=&unreserved=-_.~"),
  911    911   
            creq.params.as_deref(),
  912    912   
        );
  913    913   
    }
  914    914   
  915    915   
    #[test]
  916    916   
    fn test_signing_urls_with_percent_encoded_query_strings() {
  917    917   
        let all_printable_ascii_chars: String = (32u8..127).map(char::from).collect();
  918    918   
        let uri = Uri::from_static("https://s3.us-east-1.amazonaws.com/my-bucket");
  919    919   
  920    920   
        let mut query_writer = QueryWriter::new(&uri);
  921    921   
        query_writer.insert("list-type", "2");
  922    922   
        query_writer.insert("prefix", &all_printable_ascii_chars);
  923    923   
  924         -
        let req = http0::Request::builder()
         924  +
        let req = http::Request::builder()
  925    925   
            .uri(query_writer.build_uri())
  926    926   
            .body("")
  927    927   
            .unwrap()
  928    928   
            .into();
  929    929   
        let req = SignableRequest::from(&req);
  930    930   
        let identity = Credentials::for_tests().into();
  931    931   
        let signing_params = signing_params(&identity, SigningSettings::default());
  932    932   
        let creq = CanonicalRequest::from(&req, &signing_params).unwrap();
  933    933   
  934    934   
        let expected = "list-type=2&prefix=%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~";
  935    935   
        let actual = creq.params.unwrap();
  936    936   
        assert_eq!(expected, actual);
  937    937   
    }
  938    938   
  939    939   
    #[test]
  940    940   
    fn test_omit_session_token() {
  941    941   
        let test = SigningSuiteTest::v4("get-vanilla-query-order-key-case");
  942    942   
        let req = test.request();
  943    943   
        let req = SignableRequest::from(&req);
  944    944   
        let settings = SigningSettings {
  945    945   
            session_token_mode: SessionTokenMode::Include,
  946    946   
            ..Default::default()
  947    947   
        };
  948    948   
        let identity = Credentials::for_tests_with_session_token().into();
  949    949   
        let mut signing_params = signing_params(&identity, settings);
  950    950   
  951    951   
        let creq = CanonicalRequest::from(&req, &signing_params).unwrap();
  952    952   
        assert_eq!(
  953    953   
            creq.values.signed_headers().as_str(),
  954    954   
            "host;x-amz-date;x-amz-security-token"
  955    955   
        );
  956    956   
        assert_eq!(
  957    957   
            creq.headers.get("x-amz-security-token").unwrap(),
  958    958   
            "notarealsessiontoken"
  959    959   
        );
  960    960   
  961    961   
        signing_params.set_session_token_mode(SessionTokenMode::Exclude);
  962    962   
        let creq = CanonicalRequest::from(&req, &signing_params).unwrap();
  963    963   
        assert_eq!(
  964    964   
            creq.headers.get("x-amz-security-token").unwrap(),
  965    965   
            "notarealsessiontoken"
  966    966   
        );
  967    967   
        assert_eq!(creq.values.signed_headers().as_str(), "host;x-amz-date");
  968    968   
    }
  969    969   
  970    970   
    // It should exclude authorization, user-agent, x-amzn-trace-id, and transfer-encoding headers from presigning
  971    971   
    #[test]
  972    972   
    fn non_presigning_header_exclusion() {
  973         -
        let request = http0::Request::builder()
         973  +
        let request = http::Request::builder()
  974    974   
            .uri("https://some-endpoint.some-region.amazonaws.com")
  975    975   
            .header("authorization", "test-authorization")
  976    976   
            .header("content-type", "application/xml")
  977    977   
            .header("content-length", "0")
  978    978   
            .header("user-agent", "test-user-agent")
  979    979   
            .header("x-amzn-trace-id", "test-trace-id")
  980    980   
            .header("x-amz-user-agent", "test-user-agent")
  981    981   
            .header("transfer-encoding", "chunked")
  982    982   
            .body("")
  983    983   
            .unwrap()
  984    984   
            .into();
  985    985   
        let request = SignableRequest::from(&request);
  986    986   
  987    987   
        let settings = SigningSettings {
  988    988   
            signature_location: SignatureLocation::Headers,
  989    989   
            ..Default::default()
  990    990   
        };
  991    991   
  992    992   
        let identity = Credentials::for_tests().into();
  993    993   
        let signing_params = signing_params(&identity, settings);
  994    994   
        let canonical = CanonicalRequest::from(&request, &signing_params).unwrap();
  995    995   
  996    996   
        let values = canonical.values.as_headers().unwrap();
  997    997   
        assert_eq!(
  998    998   
            "content-length;content-type;host;x-amz-date;x-amz-user-agent",
  999    999   
            values.signed_headers.as_str()
 1000   1000   
        );
 1001   1001   
    }
 1002   1002   
 1003   1003   
    // It should exclude authorization, user-agent, x-amz-user-agent, x-amzn-trace-id, and transfer-encoding headers from presigning
 1004   1004   
    #[test]
 1005   1005   
    fn presigning_header_exclusion() {
 1006         -
        let request = http0::Request::builder()
        1006  +
        let request = http::Request::builder()
 1007   1007   
            .uri("https://some-endpoint.some-region.amazonaws.com")
 1008   1008   
            .header("authorization", "test-authorization")
 1009   1009   
            .header("content-type", "application/xml")
 1010   1010   
            .header("content-length", "0")
 1011   1011   
            .header("user-agent", "test-user-agent")
 1012   1012   
            .header("x-amzn-trace-id", "test-trace-id")
 1013   1013   
            .header("x-amz-user-agent", "test-user-agent")
 1014   1014   
            .header("transfer-encoding", "chunked")
 1015   1015   
            .body("")
 1016   1016   
            .unwrap()
 1017   1017   
            .into();
 1018   1018   
        let request = SignableRequest::from(&request);
 1019   1019   
 1020   1020   
        let settings = SigningSettings {
 1021   1021   
            signature_location: SignatureLocation::QueryParams,
 1022   1022   
            expires_in: Some(Duration::from_secs(30)),
 1023   1023   
            ..Default::default()
 1024   1024   
        };
 1025   1025   
 1026   1026   
        let identity = Credentials::for_tests().into();
 1027   1027   
        let signing_params = signing_params(&identity, settings);
 1028   1028   
        let canonical = CanonicalRequest::from(&request, &signing_params).unwrap();
 1029   1029   
 1030   1030   
        let values = canonical.values.into_query_params().unwrap();
 1031   1031   
        assert_eq!(
 1032   1032   
            "content-length;content-type;host",
 1033   1033   
            values.signed_headers.as_str()
 1034   1034   
        );
 1035   1035   
    }
 1036   1036   
 1037   1037   
    #[allow(clippy::ptr_arg)] // The proptest macro requires this arg to be a Vec instead of a slice.
 1038   1038   
    fn valid_input(input: &Vec<String>) -> bool {
 1039   1039   
        [
 1040   1040   
            "content-length".to_owned(),
 1041   1041   
            "content-type".to_owned(),
 1042   1042   
            "host".to_owned(),
 1043   1043   
        ]
 1044   1044   
        .iter()
 1045   1045   
        .all(|element| !input.contains(element))
 1046   1046   
    }
 1047   1047   
 1048   1048   
    proptest! {
 1049   1049   
        #[test]
 1050   1050   
        fn presigning_header_exclusion_with_explicit_exclusion_list_specified(
 1051   1051   
            excluded_headers in prop::collection::vec("[a-z]{1,20}", 1..10).prop_filter(
 1052   1052   
                "`excluded_headers` should pass the `valid_input` check",
 1053   1053   
                valid_input,
 1054   1054   
            )
 1055   1055   
        ) {
 1056         -
            let mut request_builder = http0::Request::builder()
        1056  +
            let mut request_builder = http::Request::builder()
 1057   1057   
                .uri("https://some-endpoint.some-region.amazonaws.com")
 1058   1058   
                .header("content-type", "application/xml")
 1059   1059   
                .header("content-length", "0");
 1060   1060   
            for key in &excluded_headers {
 1061   1061   
                request_builder = request_builder.header(key, "value");
 1062   1062   
            }
 1063   1063   
            let request = request_builder.body("").unwrap().into();
 1064   1064   
 1065   1065   
            let request = SignableRequest::from(&request);
 1066   1066   

tmp-codegen-diff/aws-sdk/sdk/aws-sigv4/src/http_request/error.rs

@@ -1,1 +37,37 @@
    1      1   
/*
    2      2   
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
    3      3   
 * SPDX-License-Identifier: Apache-2.0
    4      4   
 */
    5      5   
    6         -
use http0::header::{InvalidHeaderName, InvalidHeaderValue};
    7         -
use http0::uri::InvalidUri;
           6  +
use http::header::{InvalidHeaderName, InvalidHeaderValue};
           7  +
use http::uri::InvalidUri;
    8      8   
use std::error::Error;
    9      9   
use std::fmt;
   10     10   
   11     11   
#[derive(Debug)]
   12     12   
enum SigningErrorKind {
   13     13   
    FailedToCreateCanonicalRequest { source: CanonicalRequestError },
   14     14   
    UnsupportedIdentityType,
   15     15   
}
   16     16   
   17     17   
/// Error signing request