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

如何在aiohttp中从URL获取查询字符串参数?代码报错求助

问题分析与修复方案

首先,你的代码核心问题出在路由配置错误,导致request.rel_url.query根本拿不到你想要的查询参数,另外还有SQL注入风险和资源泄漏的问题,咱们一步步来修复:

1. 修正路由配置

你现在把查询参数(call_id和status)当成了URL路径的一部分,写了/{call_id}&{status},但实际上查询参数是跟在?后面的,比如正确的请求URL应该是http://localhost:8080/call-answer?call_id=123&status=completed。

所以路由应该改成普通的路径,比如:

app.router.add_get('/call-answer', call_answer)

这样当客户端发送带查询参数的请求时,request.rel_url.query才能正确解析出call_id和status。

2. 安全获取查询参数

直接用params["call_id"]如果参数不存在会抛出KeyError,建议先检查参数是否存在,或者用get方法设置默认值:

async def call_answer(request):
    params = request.rel_url.query
    # 先检查必要参数是否存在
    call_id = params.get("call_id")
    status = params.get("status")
    if not call_id or not status:
        return web.Response(
            content_type='application/json',
            status=400,
            text=json.dumps({
                'status': 'error',
                'message': 'Missing required parameters: call_id and status are required'
            }))
    # 后续逻辑...

3. 修复SQL注入风险

你现在用字符串拼接SQL的方式非常危险,会导致SQL注入攻击,psycopg2支持参数化查询,应该把参数作为第二个参数传给cursor.execute():

# 错误写法(有注入风险)
# sql = """ update calls set status = %s where id = %s; """ % (params["status"], params["call_id"])
# cursor.execute(sql)

# 正确写法(参数化查询)
sql = """UPDATE calls SET status = %s WHERE id = %s;"""
cursor.execute(sql, (status, call_id))  # 把参数放在元组里传进去

4. 避免数据库资源泄漏

每次请求创建新的数据库连接不是最优解,而且你没有关闭cursor和connection,容易导致资源泄漏。建议用with语句自动管理资源,或者使用连接池:

async def call_answer(request):
    params = request.rel_url.query
    call_id = params.get("call_id")
    status = params.get("status")
    if not call_id or not status:
        return web.Response(
            content_type='application/json',
            status=400,
            text=json.dumps({
                'status': 'error',
                'message': 'Missing required parameters: call_id and status are required'
            }))
    
    try:
        conn = psycopg2.connect(connect_str)
        with conn.cursor() as cursor:
            sql = """UPDATE calls SET status = %s WHERE id = %s;"""
            cursor.execute(sql, (status, call_id))
            conn.commit()
        return web.Response(
            content_type='application/json',
            text=json.dumps({
                'status': 'success'
            }))
    except Exception as e:
        # 如果出错,回滚事务
        if conn:
            conn.rollback()
        return web.Response(
            content_type='application/json',
            status=500,
            text=json.dumps({
                'status': 'error',
                'message': str(e)
            }))
    finally:
        # 确保连接关闭
        if conn:
            conn.close()

完整修复后的代码

把以上修改整合起来,完整代码如下:

import argparse
import logging
import json
import psycopg2
from aiohttp import web

async def call_answer(request):
    params = request.rel_url.query
    call_id = params.get("call_id")
    status = params.get("status")
    
    # 验证必填参数
    if not call_id or not status:
        return web.Response(
            content_type='application/json',
            status=400,
            text=json.dumps({
                'status': 'error',
                'message': 'Missing required parameters: call_id and status are mandatory'
            }))
    
    try:
        # 假设connect_str已经定义
        connect_str = "your_connection_string_here"
        conn = psycopg2.connect(connect_str)
        with conn.cursor() as cursor:
            # 参数化查询,避免SQL注入
            sql = """UPDATE calls SET status = %s WHERE id = %s;"""
            cursor.execute(sql, (status, call_id))
            conn.commit()
        
        return web.Response(
            content_type='application/json',
            text=json.dumps({
                'status': 'success'
            }))
    except Exception as e:
        if conn:
            conn.rollback()
        return web.Response(
            content_type='application/json',
            status=500,
            text=json.dumps({
                'status': 'error',
                'message': f'Database error: {str(e)}'
            }))
    finally:
        if conn:
            conn.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='WebRTC audio / video / data-channels demo')
    parser.add_argument('--port', type=int, default=8080, help='Port for HTTP server (default: 8080)')
    parser.add_argument('--verbose', '-v', action='count')
    args = parser.parse_args()
    
    if args.verbose:
        logging.basicConfig(level=logging.DEBUG)
    
    app = web.Application()
    # 修正路由配置
    app.router.add_get('/call-answer', call_answer)
    
    web.run_app(app, port=args.port)

现在你可以用类似这样的请求测试:

http://localhost:8080/call-answer?call_id=1&status=answered

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:57:03