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

CherryPy中_cp_dispatch无法将batch/路由至realbatch方法的问题

CherryPy _cp_dispatch 路由问题解决

问题背景

我用CherryPy实现了一个处理REST API的对象,但无法正确使用_cp_dispatch完成路由映射:

  • 期望将batch/路由到realbatch()方法,但当前配置下该方法未被调用
  • 期望将batch/{id}/product/{sku}路由到product()方法,这部分目前正常
  • 若将realbatch重命名为index,虽然能解决batch/的路由问题,但会错误匹配类似batc/的无效路径
  • 最终目标:仅匹配指定的合法路径,其他所有路径返回404

当前代码

import cherrypy

class Products(object):
    def __init__(self, product_database):
        self.product_database = product_database

    def _cp_dispatch(self, vpath):
        # batch/
        if len(vpath) == 1 and vpath[0] == "batch":
            vpath[0] = "realbatch"
            return self

        # batch/{id}/product/
        if len(vpath) == 3 and vpath[0] == "batch":            
            vpath.pop(0)        # pop "batch"
            cherrypy.request.params['batch_id'] = vpath.pop(0)
            return self
        
        # batch/{id}/product/{sku}/
        if len(vpath) == 4 and vpath[0] == "batch" and vpath[2] == "product":
            vpath.pop(0)        # pop "batch"
            cherrypy.request.params['batch_id'] = vpath.pop(0)
            vpath.pop(0)        # pop "product"
            cherrypy.request.params['sku'] = vpath[0]
            vpath[0] = "product"
            return self
        
        # defaults
        return self

    # POST   rest-products/batch      --> create a batch (name in JSON body), return batch id
    # GET    rest-products/batch      --> return list of batches
    @cherrypy.expose
    @cherrypy.tools.json_out()
    def realbatch(self):
        # this method is not called when calling "batch/"
        pass

    # POST   rest-products/batch/{id}/product --> add product to batch (product data in JSON body)
    @cherrypy.expose
    @cherrypy.tools.json_out()
    def product(self, batch_id, sku = None):
        # this method is called when calling "batch/{id}/product/" or "batch/{id}/product/{sku}"
        pass

问题分析

你对_cp_dispatch的调用时机理解有误:CherryPy不会在方法匹配失败后才调用它,而是在尝试匹配任何方法之前就执行_cp_dispatch来修改路径。当前代码的核心问题是:

  1. 默认返回self会让CherryPy继续尝试匹配当前对象的其他方法(如index),导致无效路径被错误处理
  2. batch/的路径修改逻辑本身是正确的,但需要确保后续路径匹配时能精准找到realbatch方法

修正方案

调整后的_cp_dispatch实现

import cherrypy

class Products(object):
    def __init__(self, product_database):
        self.product_database = product_database

    def _cp_dispatch(self, vpath):
        # 精确匹配 batch/
        if len(vpath) == 1 and vpath[0] == "batch":
            vpath[0] = "realbatch"
            return self

        # 精确匹配 batch/{id}/product/
        if len(vpath) == 3 and vpath[0] == "batch" and vpath[2] == "product":
            vpath.pop(0)  # 移除"batch"
            cherrypy.request.params['batch_id'] = vpath.pop(0)  # 提取batch_id
            return self
        
        # 精确匹配 batch/{id}/product/{sku}/
        if len(vpath) == 4 and vpath[0] == "batch" and vpath[2] == "product":
            vpath.pop(0)  # 移除"batch"
            cherrypy.request.params['batch_id'] = vpath.pop(0)  # 提取batch_id
            vpath.pop(0)  # 移除"product"
            cherrypy.request.params['sku'] = vpath.pop(0)  # 提取sku
            vpath.insert(0, "product")  # 重置路径为["product"],匹配product方法
            return self
        
        # 不匹配的路径返回None,直接触发404
        return None

    @cherrypy.expose
    @cherrypy.tools.json_out()
    def realbatch(self):
        # 现在访问batch/会正确调用此方法
        if cherrypy.request.method == "GET":
            # 返回批次列表逻辑
            return self.product_database.get_batches()
        elif cherrypy.request.method == "POST":
            # 创建批次逻辑
            batch_data = cherrypy.request.json
            batch_id = self.product_database.create_batch(batch_data["name"])
            return {"batch_id": batch_id}

    @cherrypy.expose
    @cherrypy.tools.json_out()
    def product(self, batch_id, sku = None):
        if cherrypy.request.method == "POST":
            # 向批次添加产品逻辑
            product_data = cherrypy.request.json
            self.product_database.add_product_to_batch(batch_id, product_data)
            return {"status": "success"}
        elif cherrypy.request.method == "GET" and sku:
            # 获取指定批次下的指定产品逻辑
            product = self.product_database.get_product_in_batch(batch_id, sku)
            return product

关键修改点

  1. 精确路径匹配:为batch/{id}/product/的匹配增加了vpath[2] == "product"条件,避免误匹配其他类似结构的路径
  2. 无效路径返回404:默认分支返回None,而不是self,CherryPy会直接返回404状态码,不会尝试匹配其他方法
  3. 明确路径重置逻辑:在处理batch/{id}/product/{sku}/时,确保修改后的vpath精准指向product方法
  4. 补充方法内部的请求逻辑:完善了realbatch和product方法的HTTP请求处理示例,让代码更完整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:27:35