2015-06-29 189 views
1

我有一个奇怪的问题;我正在运行Flask,并且我有一个API函数来取消成员身份。该网址还包含用于设置取消原因的参数。这是一个简短的文本,它可以包含扩展字符,所以该字符串由主叫方URL编码。使用URL编码参数处理请求的瓶颈问题

然而,在某些情况下,Flask在达到我自己的处理代码之前会返回400错误。例如,以下网址:

curl -X "DELETE" "http://localhost:5000/contracts/C9ABA4AA-834E-4711-91A8-F21057DF693B?date=2015-8-1&canceldate=2015-6-27&booktoday=true&overrideEnddate=true&cancelreason=traslado+a+m%C3%A1s+de+15+km&correctionreason=" 

给了我一个400错误:浏览器(或代理)发送的请求,该服务器无法理解。虽然它似乎是一个完全有效的网址。 当我捕获错误底层误差数据是:

'ascii' codec can't encode character u'\\xe1' in position 12: ordinal not in range(128) 

我发现,一切都很好,当我请从URL字符串的编码扩展的字符á(%C3%A1)。

我也可以通过将我在别处找到的这种解决方法添加到我的应用程序来解决此问题。 初始化()

import sys 
reload(sys) 
sys.setdefaultencoding("utf-8") 

我了解,这个语句强制Python解释器默认使用UTF-8解码字节串,而不是ASCII。
这给了我一个解决我的问题,但它感觉过于复杂和不谨慎。

所以,真正的问题是,我在这里错过了什么?在Flask中有一个我不知道的解决方案,或者Flask无法处理特定的URL编码字符串? 我希望Flask能够自己处理URL编码的参数,而不需要非库代码的解决方法...

我没有回溯,因为Flask会捕获它并将其作为HTTP错误处理并返回一个400 HTTP状态码。

EDIT: 异常的原点在烧瓶代码(站点包\烧瓶\ app.py)的这一部分:

def full_dispatch_request(self): 
    """Dispatches the request and on top of that performs request 
    pre and postprocessing as well as HTTP exception catching and 
    error handling. 

    .. versionadded:: 0.7 
""" 
self.try_trigger_before_first_request_functions() 
try: 
    request_started.send(self) 
    rv = self.preprocess_request() 
    if rv is None: 
     rv = self.dispatch_request() 
except Exception as e: 
    rv = self.handle_user_exception(e) 
response = self.make_response(rv) 
response = self.process_response(response) 
request_finished.send(self, response=response) 
return response 

代码跳到除外:和返回400错误。

谢谢你可以给我的任何指针。

+0

即使在使用Flask调试服务器时也没有可用的回溯? – Ketouem

+0

@Ketouem,是的,有一个追溯,但只有当我在代码中放置一个断点时。 Flask优雅地处理“错误”查询字符串,而是返回一个http错误400. –

+0

你能否在问题中包含错误视图的代码? – Ketouem

回答

1

找到解决方案;我似乎在我的问题中遗漏了一些重要信息,这是解决问题所需的。

我们试图在一个非常简单的单页Flask应用程序中复制问题,因此我可以将它放在StackOverflow的示例中。但是,简单的Flask测试页面运行良好,所以我们去寻找差异。

我完全忘记了,我们注意到,那时我们使用webargs库来解析http参数。

参数被解析为字符串,并且在webargs中还有一个类型unicode可用。将类型更改为unicode解决了问题。

@api.route('/contracts/<ppl_mshp_id>', methods=['DELETE']) 
@use_args({'date': Arg(type_=str, validate=is_date, required=False), 
      'canceldate': Arg(type_=str, validate=is_date, required=False), 
      'cancelreason': Arg(type_=unicode, required=False, default=u""), 
      'correction': Arg(type_=float, required=False), 
      'correctionreason': Arg(type_=unicode, required=False, default=u""), 
      'restitution': Arg(type_=bool, required=False, default=False), 
      'booktoday': Arg(type_=bool, required=False, default=False), 
      'overrideEnddate': Arg(type_=bool, required=False, default=False), 
      }) 
def cancel_contract(args, ppl_mshp_id): 
... 

谢谢@ketouem为您的时间和麻烦,并抱歉我的问题不完整。