我在 Mac 上的 localstack(devlocal s3 模拟器)docker 容器上运行 s3 并收到此错误(“SdkClientException:无法执行 HTTP 请求:bucketname.localhost”、“UnknownHostException”)。并且 listBuckets 有效。
将其放入 /etc/hosts 中为我解决了这个问题:
127.0.0.1 bucketname.localhost
以下替代解决方案也为我修复了该问题,但此路径样式访问不适用于 2020 年 9 月之后创建的真实 s3 存储桶(而不是 localstack s3 存储桶):
.withPathStyleAccessEnabled(true)
(添加到 AmazonS3ClientBuilder 设置行)
Why:
请注意bucket.endpoint 上的UnknownHostException - 为什么它尝试将存储桶放入DNS 名称中?:
com.amazonaws.SdkClientException: Unable to execute HTTP request: bucket.endpoint
...
Caused by: java.net.UnknownHostException: bucket.endpoint
对我来说,它是bucketname.localhost,因为我试图连接到在本地主机上运行的localstack S3端点。
新的 S3 存储桶命名使用虚拟托管样式命名,其中存储桶位于路径的前面。bucketname.s3.amazonaws.com
not s3.amazonaws.com/bucketname
虚拟托管风格是默认的。
AWS 已弃用路径样式命名。 2020 年 9 月之后创建的所有存储桶都不能使用路径样式。更多信息:https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story
localstack 已经实现了对虚拟主机样式的支持,但如果您在 Docker 容器中本地运行它,则必须为每个存储桶名称创建主机别名。https://github.com/localstack/localstack/issues/2631 https://github.com/localstack/localstack/issues/2631
当在 linux 中运行 docker 时(并使用 systemd-resolved - Fedora/Ubuntu ),它可以工作。我认为这是因为以下行在 Linux 上有效,但在 Mac 上无效:ping abc.localhost
(其中 abc 可以是任何东西)。这称为 localhost 子域。
对于 Mac(或不使用 systemd-resolved 的 Linux),另一个选项是将行添加到 /etc/hosts 或使用brew install dnsmasq
(dnsmasq 也在 Linux 上)-https://serverfault.com/questions/118378/in-my-etc-hosts-file-on-linux-osx-how-do-i-do-a-wildcard-subdomain#118589 https://serverfault.com/questions/118378/in-my-etc-hosts-file-on-linux-osx-how-do-i-do-a-wildcard-subdomain#118589.
Linux systemd 解析的 localhost-subdomain 信息来源:https://unix.stackexchange.com/questions/401966/how-does-every-subdomain-of-localhost-point-to-localhost-on-fedora https://unix.stackexchange.com/questions/401966/how-does-every-subdomain-of-localhost-point-to-localhost-on-fedora
我跟踪了此点的虚拟主机主机名:(sdk 版本 1.11)
AmazonS3Client.doesObjectExist
getObjectMetadata
createRequest
resolveRequestEndpoint
new S3RequestEndpointResolver(..)
S3RequestEndpointResolver.resolveRequestEndpoint
shouldUseVirtualAddressing
BucketNameUtils.isDNSBucketName
isValidV2BucketName
isValidV2BucketName
request.setEndpoint(convertToVirtualHostEndpoint(endpoint, bucketName));