2010-04-26 13 views
12

Qual è l'approccio migliore per creare un web API RESTful in CherryPy? Mi sono guardato intorno da qualche giorno e niente sembra fantastico. Per Django sembra che ci siano molti strumenti per farlo, ma non per CherryPy o non ne sono a conoscenza.CherryPy e RESTful web api

Successivamente modificare: Come devo usare CherryPy per trasformare una richiesta come/GetOrders rappresentano = X & type = Y in una sorta/ordini/account/tipo?

risposta

1

Suppongo che tu abbia provato le corrispondenze parziali come discusso nel tutorial. Trovo che anche se non eccezionale, ottiene il lavoro fatto la maggior parte del tempo.

Oltre a ciò, sebbene non l'abbia provato, Cherrypy supporta apparentemente Routes (vedere http://www.cherrypy.org/wiki/PageHandlers), che offre tutti i tipi di opzioni RESTful.

+0

Collegamenti per non funziona :( –

11

Non so se è il modo "migliore", ma ecco come lo faccio:

import cherrypy 

class RESTResource(object): 
    """ 
    Base class for providing a RESTful interface to a resource. 

    To use this class, simply derive a class from it and implement the methods 
    you want to support. The list of possible methods are: 
    handle_GET 
    handle_PUT 
    handle_POST 
    handle_DELETE 
    """ 
    @cherrypy.expose 
    def default(self, *vpath, **params): 
     method = getattr(self, "handle_" + cherrypy.request.method, None) 
     if not method: 
     methods = [x.replace("handle_", "") 
      for x in dir(self) if x.startswith("handle_")] 
     cherrypy.response.headers["Allow"] = ",".join(methods) 
     raise cherrypy.HTTPError(405, "Method not implemented.") 
     return method(*vpath, **params); 

class FooResource(RESTResource): 
    def handle_GET(self, *vpath, **params): 
     retval = "Path Elements:<br/>" + '<br/>'.join(vpath) 
     query = ['%s=>%s' % (k,v) for k,v in params.items()] 
     retval += "<br/>Query String Elements:<br/>" + \ 
      '<br/>'.join(query) 
     return retval 

class Root(object): 
    foo = FooResource() 

    @cherrypy.expose 
    def index(self): 
     return "REST example." 

cherrypy.quickstart(Root()) 

È sufficiente derivare dalla classe RESTResource e gestire qualunque verbi RESTful desiderato (GET, PUT, POST, DELETE) con un metodo con lo stesso nome prefissato con handle_. Se non gestisci un particolare verbo (come POST), la classe base genererà un errore 405 Method Not Implemented.

Gli elementi del percorso vengono passati in vpaths e tutte le stringhe di query vengono passate in params. Utilizzando il codice di esempio sopra, se si dovesse richiedere /foo/bar?woo=hoo, vpath[0] sarebbe bar e params sarebbe {'woo': 'hoo'}.

1

Per rispondere alla tua seconda domanda, si desidera definire ed esporre un metodo di default:

class getOrders(Object): 
    def default(account, type): 
     ... 

    default.exposed = True 

utilizzando questo metodo, GetOrders/x/y sarebbe mappare default(account='x', type='y'). Come ha detto qualcun altro, non è grandioso, ma ha fatto il lavoro.

Per quanto riguarda le applicazioni REST, sono abbastanza sicuro che il gestore di pagine predefinito funzioni per tale applicazione.

7

Poiché HTTP definisce questi metodi di chiamata, il modo più diretto per attuare residuo con CherryPy è quello di utilizzare la MethodDispatcher invece del dispatcher predefinito.

altro si possono trovare nei documenti CherryPy: http://cherrypy.readthedocs.io/en/latest/tutorials.html#tutorial-7-give-us-a-rest

Qui è anche la descrizione dettagliata su come inviare e ricevere JSON utilizzando CherryPy Strumenti: http://tools.cherrypy.org/wiki/JSON

+0

Ultimo collegamento è andato ora. –

2

Così si vuole trasformare/GetOrders? account = X & type = Y in qualcosa come/orders/account/type usando Cherrypy.

Vorrei provare l'approccio utilizzato in http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html come menzionato da @Tomasz Blachowicz, con alcune modifiche.

Ricordate che è possibile gestire qualcosa come/ordine/account/tipo con

@cherrypy.expose 
def order(account=None, type=None): 
    print account, type 

class Root(object): 
    pass 

root = Root() 
root.orders = orders 


cherrypy.quickstart(root, '/') 

Quindi, se si prende l'esempio dato in http://cherrypy.readthedocs.org/en/latest/tutorial/REST.html, è possibile modificarlo per gestire questo tipo di URL.

class Orders(object): 
    exposed = True 
    def __init__(self): 
     pass 

    def GET(self, account=None, type=None): 
     #return the order list for this account type 
     return getOrders(account, type) 

    def PUT(self, account=None, type=None, orders=None): 
     #Set the orders associated with account or something 
     setOrders(account, type, orders) 


class Root(object): 
    pass 

root = Root() 
root.orders = Orders() 

conf = { 
    'global': { 
     'server.socket_host': '0.0.0.0', 
     'server.socket_port': 8000, 
    }, 
    '/': { 
     'request.dispatch': cherrypy.dispatch.MethodDispatcher(), 
    }, 
} 

cherrypy.quickstart(root, '/', conf) 

Perché si vuole impostare gli ordini che utilizzano tale metodo put non lo so, ma lo fa fare un altro esempio di come fare PUT metodi. Tutto quello che devi fare è sostituire il metodo usato da una richiesta con PUT e userà il metodo PUT() degli ordini e userà un GET regolare sugli ordini e userà il metodo GET(). Poiché un metodo POST() non è definito, con questo esempio non è possibile utilizzare POST. Se provi POST o DELETE otterrai "405 Method Not Allowed".

Mi piace questo approccio perché è facile vedere cosa sta succedendo e, credo, risponda alla tua domanda.