2015-06-29 186 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爲您的時間和麻煩,並抱歉我的問題不完整。