2011-12-08 12 views
2

データベースからタイルをロードする要求に応答して返す単純なツイスターHTTPサーバーを実装しようとしています。しかし、私は要求文字列をかなり奇妙に解釈する方法を見つける。Twisted(python)でリクエスト文字列を正しく解析する方法

これは私がサーバーに投稿するものである:

curl -d "request=loadTiles&grid[0][x]=17&grid[0][y]=185&grid[1][x]=18&grid[1][y]=184" http://localhost:8080/fetch/ 

私はrequest.argsがあることを期待するもの:

ツイストは request.argsをどのように解釈するか
{'request': 'loadTiles', 'grid': [{'x': 17, 'y': 185}, {'x': 18, 'y': 184}]} 

{'grid[1][y]': ['184'], 'grid[0][y]': ['185'], 'grid[1][x]': ['18'], 'request': ['loadTiles'], 'grid[0][x]': ['17']} 

はそれが可能です自動的にリクエスト文字列を解析してgrのリストを作成させるidパラメータを使用するか、手動で行う必要がありますか?

私はjsonがグリッドパラメータをエンコードし、それをサーバー側でデコードすることができましたが、それは不要なハックのようです。

答えて

1

おそらく、パーサーの代わりに、request.argsを後処理する方法はありますか?これはまた、単に0番目の要素の値に単一要素のリストを簡素化し、実際の整数に数値文字列に変換することを

from pyparsing import Suppress, alphas, alphanums, nums, Word 
from itertools import groupby 

# you could do this with regular expressions too, if you prefer 
LBRACK,RBRACK = map(Suppress, '[]') 
ident = Word('_' + alphas, '_' + alphanums) 
integer = Word(nums).setParseAction(lambda t : int(t[0])) 
subscriptedRef = ident + 2*(LBRACK + (ident | integer) + RBRACK) 


def simplify_value(v): 
    if isinstance(v,list) and len(v)==1: 
     return simplify_value(v[0]) 
    if v == integer: 
     return int(v) 
    return v 

def regroup_args(dd): 
    ret = {} 
    subscripts = [] 
    for k,v in dd.items(): 
     # this is a pyparsing short-cut to see if a string matches a pattern 
     # I also used it above in simplify_value to test for integerness of a string 
     if k == subscriptedRef: 
      subscripts.append(tuple(subscriptedRef.parseString(k))+ 
            (simplify_value(v),)) 
     else: 
      ret[k] = simplify_value(v) 

    # sort all the matched subscripted args, and then use groupby to 
    # group by name and list index 
    # this assumes all indexes 0-n are present in the parsed arguments 
    subscripts.sort() 
    for name,nameitems in groupby(subscripts, key=lambda x:x[0]): 
     ret[name] = [] 
     for idx,idxitems in groupby(nameitems, key=lambda x:x[1]): 
      idd = {} 
      for item in idxitems: 
       name, i, attr, val = item 
       idd[attr] = val 
      ret[name].append(idd) 

    return ret 

request_args = {'grid[1][y]': ['184'], 'grid[0][y]': ['185'], 'grid[1][x]': ['18'], 'request': ['loadTiles'], 'grid[0][x]': ['17']} 
print regroup_args(request_args) 

プリント

{'grid': [{'y': 185, 'x': 17}, {'y': 184, 'x': 18}], 'request': 'loadTiles'} 

注意。

+0

ありがとう、私が必要としたもの。 – element

4

私はなぜあなたのurlencodedデータがいくつかの臨時の非標準規則に従ってデコードされるとは思っていません。 [はクエリ文字列では特別ではありません。このようにソフトウェアをデコードするソフトウェアは何ですか?

いずれにしても、これは実際にはツイストではなく、Pythonです(より一般的には、このデータを解析する方法はweb-standardです)。対話形式でcgi.parse_qs関数を使用して返されるデータの種類を確認できます。例:

>>> import cgi 
>>> cgi.parse_qs("") 
{} 
>>> cgi.parse_qs("x=1") 
{'x': ['1']} 
>>> cgi.parse_qs("x[something]=1") 
{'x[something]': ['1']} 
>>> cgi.parse_qs("x=1&y=2") 
{'y': ['2'], 'x': ['1']} 
>>> cgi.parse_qs("x=1&y=2&x=3") 
{'y': ['2'], 'x': ['1', '3']} 

私はあなたのために物事をクリアすることを望む。

+0

ありがとうございました。私はPHPから来て、ポール・マクガイアが自動的に後処理を行ってGETとPOSTリクエストを処理します。 – element

関連する問題