2011-12-06 141 views
0

在Tornado中,你如何区分不同的请求类型?另外,分离请求的正确方法是什么?在结束时,如果我去/item/1.xml,我想XML,/item/1.html是一个正确的HTML视图等在Tornado中渲染请求类型

喜欢的东西:

def getXML(): 
    return self.render('somexmlresult.xml') 

def getHTML(): 
    return self.rendeR('htmlresult.html') 

def get(): 
    if request == 'xml': 
     return self.render('somexmlresult.xml') 
    elif request == 'html': 
     return self.render('htmlresult.html') 

编辑〜我是射击沿看到here

回答

1

首先考虑,成立了处理程序,在一个宁静的风格URI算一个例子。我们使用正则表达式的2块找一个ID和一个潜在的请求格式(即HTML,XML,JSON等)现在

class TaskServer(tornado.web.Application): 
    def __init__(self, newHandlers = [], debug = None): 
     request_format = "(\.[a-zA-Z]+$)?" 
     baseHandlers = [ 
      (r"/jobs" + request_format, JobsHandler), 
      (r"/jobs/", JobsHandler), 
      (r"/jobs/new" + request_format, NewJobsHandler), 
      (r"/jobs/([0-9]+)/edit" + request_format, EditJobsHandler) 
     ] 
     for handler in newHandlers: 
      baseHandlers.append(handler) 


    tornado.web.Application.__init__(self, baseHandlers, debug = debug) 

,在处理程序定义一个可重复使用的功能parseRestArgs(我把我的一个BaseHandler但粘贴它在这里为了便于理解/节省空间)将ID和请求格式分开。既然你应该以特定的顺序期待id,我会把它们放在一个列表中。

get函数可以抽象以上,但它显示出分裂的逻辑放到不同的请求格式的基本思想......

class JobsHandler(BaseHandler): 
    def parseRestArgs(self, args): 
     idList = [] 
     extension = None 
     if len(args) and not args[0] is None: 
      for arg in range(len(args)): 
       match = re.match("[0-9]+", args[arg]) 
       if match: 
        slave_id = int(match.groups()[0]) 

      match = re.match("(\.[a-zA-Z]+$)", args[-1]) 
      if match: 
       extension = match.groups()[0][1:] 

     return idList, extension 

    def get(self, *args): 
     ### Read 
     job_id, extension = self.parseRestArgs(args) 

     if len(job_id): 
      if extension == None or "html": 
       #self.render(html) # Show with some ID voodoo 
       pass 
      elif extension == 'json': 
       #self.render(json) # Show with some ID voodoo 
       pass 
      else: 
       raise tornado.web.HTTPError(404) #We don't do that sort of thing here... 
     else: 
      if extension == None or "html": 
       pass 
       # self.render(html) # Index- No ID given, show an index 
      elif extension == "json": 
       pass 
       # self.render(json) # Index- No ID given, show an index 
      else: 
       raise tornado.web.HTTPError(404) #We don't do that sort of thing here... 
2

的轨道执行线的东西我宁愿一个自我描述的URL像RESTfu l应用程序。不需要url部分来表示资源的格式。 http://www.enterprise.com/customer/abc/order/123必须表示资源,而不管它是否为xml/html/json。发送请求格式的一种方式是将其作为请求参数之一发送。

http://www.enterprise.com/customer/abc/order/123?mimetype=application/xml 
http://www.enterprise.com/customer/abc/order/123?mimetype=application/json 
http://www.enterprise.com/customer/abc/order/123?mimetype=text/html 

使用请求参数序列化为适当的格式。

+0

编辑后以相同的,但我真的打算一个面向用户的像[rails](http://api.rubyonrails.org/classes/Mime/Type.html)中所见的RESTful api的实现 – odgrim

1

mimetype是这样做的正确方法,但是我可以看到最终用户想要更简单的方式访问他们希望的格式的数据。

为了保持与符合标准的库等的兼容性,您最终应根据请求的mimetype确定响应类型,并在头中使用适当的mimetype进行响应。

的方式来实现这一点的同时不破坏任何东西会增加分析器,检查请求该定义的后缀,该路线可到,如果它和MIME类型是响应,元组匹配的后缀的URI尚未指定将传入的mimetype更改为后缀的正确类型。

确保最终决定是基于提供的mimetype而不是后缀。

这样其他人可以在你的方式RESTful服务交互的使用,你仍然可以保持易用性对于人类等

〜编辑〜

继承人,用来检查一个例子正则表达式看如果以.js |结尾.html | .xml |以.json。这假设你给出完整的URI。

(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*\.(?:js|html|xml|json))(?:\?([^#]*))?(?:#(.*))? 

下面是一个更容易理解,但不太可靠

^https?://(?:[a-z\-]+\.)+[a-z]{2,6}(?:/[^/#?]+)+\.(?:js|html|xml|json)$ 

这些正则表达式的是从rfc2396