代码之家  ›  专栏  ›  技术社区  ›  Michal Charemza

如果使用HTTP/1.1,模拟S3服务器将暂停

  •  0
  • Michal Charemza  · 技术社区  · 8 年前

    我正在编写一个测试,其中使用 http.server.HTTPServer / http.server.BaseHTTPRequestHandler ,以测试涉及Boto的S3Transfer的多部分下载行为。

    除非我指定服务器使用 HTTP/1.1 . 在这种情况下,它将下载100mb文件的2个8mb部分,然后挂起。我想让模拟服务器使用 HTTP/1.1 因为这是真正的S3使用的(我相信)。

    下面是该测试的简化版本,可以由。。。

    pip3 install boto3
    python3 test.py    
    

    # test.py
    
    import http.server
    import re
    import threading
    
    import boto3
    from botocore import (
        UNSIGNED,
    )
    from botocore.client import (
        Config,
    )
    
    length = 100 * 2**20
    
    class MockS3(http.server.BaseHTTPRequestHandler):
        # If the below line is commented, the download completes
        protocol_version = 'HTTP/1.1'
    
        def do_GET(self):
            range_header = self.headers['Range']
            match = re.search(r'^bytes=(\d+)-(\d*)', range_header)
            start_inclusive_str, end_inclusive_str = match.group(1), match.group(2)
            start = int(start_inclusive_str)
            end = int(end_inclusive_str) + 1 if end_inclusive_str else length
            bytes_to_send = end - start
    
            self.send_response(206)
            self.send_header('Content-Length', str(bytes_to_send))
            self.end_headers()
            self.wfile.write(bytearray(bytes_to_send))
    
        def do_HEAD(self):
            self.send_response(200)
            self.send_header('Content-Length', length)
            self.end_headers()
    
    server_address = ('localhost', 5678)
    server = http.server.HTTPServer(server_address, MockS3)
    thread = threading.Thread(target=server.serve_forever)
    thread.daemon = True
    thread.start()
    
    class Writable():
        def write(self, data):
            pass
    
    s3_client = boto3.client('s3',
      endpoint_url='http://localhost:5678',
      config=Config(signature_version=UNSIGNED),
    )
    
    s3_client.download_fileobj(
      Bucket='some',
      Key='key',
      Fileobj=Writable(),
    )
    

    请注意 Writable 是故意的 可查找:在我的真实代码中,我使用的是一个不可查找的类文件对象。

    moto 可以 用于制作模拟S3,我这样做是为了其他测试,但对于这个特定的测试,我想要“真正的”服务器。涉及到自定义文件对象,希望确保S3Transfer和其他与此问题无关的代码按照我的预期一起工作。

    如何设置使用 HTTP/1.1 S3Transfer可以从下载吗?

    1 回复  |  直到 8 年前
        1
  •  1
  •   erip Jigar Trivedi    8 年前

    线程逻辑中存在错误。您当前所做的是在一个单独的线程上提供服务,但您真正想要做的是同时处理多个线程上的请求。

    这可以通过创建 非常愚蠢 HTTP服务器只是混合了线程功能:

    class ThreadingServer(ThreadingMixIn, HTTPServer):
        pass
    

    并从该服务器而不是从基础服务器提供服务 HTTPServer .

    至于为什么这与 HTTP/1.0 ,在为单个请求提供服务后,连接关闭。