You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask处理GET请求时遇'tuple'无法转为整数错误求解决

搭建Flask代理服务器转发请求到Google时遇到TypeError错误

我正在搭建一个代理服务器(术语是否正确?),目标是把Flask Web服务器收到的所有请求转发到google.com,再把结果返回给用户。比如访问127.0.0.1/search?q=stack%20overflow时,应该返回google.com/search?q=stack%20overflow的内容。

错误出在Flask而非我的代码中。
感谢@LukeWoodward指出这一点。

我的代码

from flask import Flask, request, Response
import requests
import urllib.parse

app = Flask(__name__)

# Add percent codes (like %20) to URLs
def add_percent_codes(urlsection):
    return urllib.parse.quote(urlsection.encode('utf8'))


def parse_sent_args(args_dict):
    args_str = '?'
    for key in args_dict:
        args_str += str(key) + '=' + str(args_dict[key]) + '&'
    return args_str[:-1]


# Define the handling function for every packet
def forward_packet(packet):
    # Modify or process the packet as needed
    print('Received packet:', packet)

    try:
        # Forward the packet to Google.com
        google_response = requests.get('https://www.google.com/' + packet)
        response_to_return = \
            [google_response.content.decode('utf8', errors='ignore'),
             int(google_response.status_code),
             bytes(google_response.headers.items()).decode('utf8', errors='ignore')]
        print('Forwarded packet to Google.com.')

        # Return the response
        return response_to_return
    

    except requests.exceptions.HTTPError as e:
        print('Error forwarding packet:', e)
        return 'HTTPError occurred: {}'.format(e), 500
    

    except requests.exceptions.RequestException as e:
        print('Error forwarding packet:', e)
        return 'RequestException occurred: {}'.format(e), 500
    
def handle_get_request(path):
    try:
        # Call the handling function for the packet
        response = forward_packet(path)
        
        return response
    finally: pass
    #except Exception as e:
        #print('Error handling GET request:\n')
        #return str(e), 500
    
@app.route('/<path:path>', methods=['GET'])
def handle_get(path):
    # Get the incoming packet from the URL path
    args_dict = dict(request.args)
    end_url_args = parse_sent_args(args_dict)
    full_path = '/' + path + end_url_args
    return handle_get_request(path)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

错误信息

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/eesa/Code/proxyforblocking/attempt2.py", line 63, in handle_get
    return handle_get_request(path)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/eesa/Code/proxyforblocking/attempt2.py", line 49, in handle_get_request
    response = forward_packet(path)
               ^^^^^^^^^^^^^^^^^^^^
  File "/home/eesa/Code/proxyforblocking/attempt2.py", line 30, in forward_packet
    bytes(google_response.headers.items()).decode('utf8', errors='ignore')]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'tuple' object cannot be interpreted as an integer

小提示:我注释掉了错误处理以获取完整的回溯信息,并添加了finally块以避免其他错误。


解决方案

1. 错误根源

报错的核心是bytes(google_response.headers.items())这行代码:headers.items()返回的是由(键, 值)元组组成的迭代器,直接传给bytes()会触发TypeError——因为bytes()只接受整数、整数序列或字符串作为参数,无法直接处理元组迭代器。

另外代码还有两个隐性问题:

  • handle_get函数拼接了带参数的full_path,但并未传给handle_get_request,导致转发到Google的请求丢失URL参数
  • 返回给Flask的响应格式不符合规范,手动处理响应头的方式错误

2. 修正后的代码

from flask import Flask, request, Response
import requests

app = Flask(__name__)

@app.route('/<path:path>', methods=['GET'])
def handle_get(path):
    # 拼接完整的目标URL,包含原请求的所有参数
    full_url = f'https://www.google.com/{path}'
    if request.args:
        full_url += '?' + request.query_string.decode('utf-8')
    
    try:
        # 转发请求到Google,过滤原请求的Host头避免被拒绝
        google_response = requests.get(
            full_url,
            headers={k: v for k, v in request.headers if k.lower() != 'host'},
            allow_redirects=False
        )
        
        # 用Flask的Response对象构造合法响应,直接复用Google的状态码、头和内容
        response = Response(
            google_response.content,
            status=google_response.status_code,
            headers=dict(google_response.headers)
        )
        return response
    
    except requests.exceptions.HTTPError as e:
        return f'HTTPError occurred: {e}', 500
    except requests.exceptions.RequestException as e:
        return f'RequestException occurred: {e}', 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

3. 关键修正点

  • 用request.query_string直接获取已编码的参数,避免手动拼接时的编码错误
  • 用Flask原生Response对象构造返回结果,正确传递响应状态码和头信息,无需手动解码内容
  • 转发请求时过滤掉Host头,防止Google拒绝非官方Host的请求
  • 移除冗余的辅助函数,简化逻辑结构
  • 确保转发的URL包含完整路径和参数,解决原代码中参数丢失的问题

内容的提问来源于stack exchange,提问作者imeesa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 12:25:11