使用 boto3 的 S3 预签名 post 网址问题
S3 presigned post urls issue using boto3
我有一个在后端使用 apache2 运行 python-flask 服务的 webapp。该应用程序托管在 Linode 上,并严重依赖其 S3 对象存储。我正在使用 boto3
与 S3 存储进行交互。我的问题是关于生产中使用的 generate_presigned_url
方法。它returns以下结构:
{
'url': 'https://eu-central-1.linodeobjects.com/my-s3-bucket',
'fields': {
'ACL': 'private',
'key': 'foo.bar',
'AWSAccessKeyId': 'FOOBAR',
'policy': 'base64longhash...',
'signature': 'foobar'
}
}
每次我在同一个 python 会话中使用此方法时,policy
键 returns 一个更长的值(每个后续请求的长度增加约 1.5 倍)。在几次请求后,policy
的大小变得非常大(数十 MB)并且应用程序中断。如果我重新启动 python 服务,policy
大小会重置。
在 boto3
文档和 GitHub 中的一些线程和此处进行挖掘后,我找不到任何关于重置 S3 连接而无需重新启动整个连接的帮助 python 会话。定期重启 apache2 服务不是一个好方法,所以我的解决方案是使用 subprocess
从独立脚本调用 generate_presigned_url
并在使用之前将字符串输出解析回 json ,这并不理想,因为我希望我不必一直从 apache 内部调用 bash 脚本。我使用的主要功能如下:
AWS_BUCKET_PARAMS = {'ACL': 'private'}
# connect to my linode's s3 bucket
def awsSign():
return boto3.client('s3', aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY, endpoint_url=AWS_ENDPOINT_URL)
# generate presigned post object for uploading files
def awsPostForm(file_path):
s3 = awsSign()
return s3.generate_presigned_post(AWS_BUCKET, file_path, AWS_BUCKET_PARAMS, [AWS_BUCKET_PARAMS], 1800)
# generate post object from external script
def awsPostFormTerminal(file_path):
from subprocess import Popen, PIPE
cmd = [ 'python3', '-c', f'from utils import awsPostForm; print(awsPostForm("{file_path}"))' ]
output = Popen( cmd, stdout=PIPE ).communicate()[0]
return json.loads(output.decode('utf-8').replace('\n', '').replace("'", '"'))
无论为文件列表调用 awsSign()
一次还是多次,都会出现此问题。
简而言之,我希望有一种更好的方法来在同一个 python 会话中从 generate_presigned_url
中检索后续的 post
表单,而无需在每个新会话中增加 policy
要求。如果有重新启动 boto3
连接的正确方法,请提供我在设置 API 调用时遗漏的一些参数,或者它可能是 Linode 的 S3 对象存储服务所特有的。
如果有人能指出正确的方向,我将不胜感激!
好吧,事实证明这是一个新手错误 - 从 linode's Q&A 得到提示。所以,回答我自己的问题:
结果是 AWS_BUCKET_PARAMS
变量在通过 generate_presigned_post
后通过引用更新。在发送请求之前复制函数范围内的全局变量解决了这个问题。
我有一个在后端使用 apache2 运行 python-flask 服务的 webapp。该应用程序托管在 Linode 上,并严重依赖其 S3 对象存储。我正在使用 boto3
与 S3 存储进行交互。我的问题是关于生产中使用的 generate_presigned_url
方法。它returns以下结构:
{
'url': 'https://eu-central-1.linodeobjects.com/my-s3-bucket',
'fields': {
'ACL': 'private',
'key': 'foo.bar',
'AWSAccessKeyId': 'FOOBAR',
'policy': 'base64longhash...',
'signature': 'foobar'
}
}
每次我在同一个 python 会话中使用此方法时,policy
键 returns 一个更长的值(每个后续请求的长度增加约 1.5 倍)。在几次请求后,policy
的大小变得非常大(数十 MB)并且应用程序中断。如果我重新启动 python 服务,policy
大小会重置。
在 boto3
文档和 GitHub 中的一些线程和此处进行挖掘后,我找不到任何关于重置 S3 连接而无需重新启动整个连接的帮助 python 会话。定期重启 apache2 服务不是一个好方法,所以我的解决方案是使用 subprocess
从独立脚本调用 generate_presigned_url
并在使用之前将字符串输出解析回 json ,这并不理想,因为我希望我不必一直从 apache 内部调用 bash 脚本。我使用的主要功能如下:
AWS_BUCKET_PARAMS = {'ACL': 'private'}
# connect to my linode's s3 bucket
def awsSign():
return boto3.client('s3', aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY, endpoint_url=AWS_ENDPOINT_URL)
# generate presigned post object for uploading files
def awsPostForm(file_path):
s3 = awsSign()
return s3.generate_presigned_post(AWS_BUCKET, file_path, AWS_BUCKET_PARAMS, [AWS_BUCKET_PARAMS], 1800)
# generate post object from external script
def awsPostFormTerminal(file_path):
from subprocess import Popen, PIPE
cmd = [ 'python3', '-c', f'from utils import awsPostForm; print(awsPostForm("{file_path}"))' ]
output = Popen( cmd, stdout=PIPE ).communicate()[0]
return json.loads(output.decode('utf-8').replace('\n', '').replace("'", '"'))
无论为文件列表调用 awsSign()
一次还是多次,都会出现此问题。
简而言之,我希望有一种更好的方法来在同一个 python 会话中从 generate_presigned_url
中检索后续的 post
表单,而无需在每个新会话中增加 policy
要求。如果有重新启动 boto3
连接的正确方法,请提供我在设置 API 调用时遗漏的一些参数,或者它可能是 Linode 的 S3 对象存储服务所特有的。
如果有人能指出正确的方向,我将不胜感激!
好吧,事实证明这是一个新手错误 - 从 linode's Q&A 得到提示。所以,回答我自己的问题:
结果是 AWS_BUCKET_PARAMS
变量在通过 generate_presigned_post
后通过引用更新。在发送请求之前复制函数范围内的全局变量解决了这个问题。