2010-12-27 5 views
11

Sto provando ad usare Piston per fornire supporto REST a Django. Ho implementato i miei gestori come da documentazione fornita. Il problema è che posso "leggere" e "cancellare" la mia risorsa ma non posso "creare" o "aggiornare". Ogni volta che colpisco l'api pertinente ottengo 400 errori di richiesta errata.Ricevo un errore di 400 Bad Request durante l'utilizzo del pistone django

Ho esteso la classe di risorse per CSRF utilizzando questo frammento di codice comunemente disponibili:

class CsrfExemptResource(Resource): 
    """A Custom Resource that is csrf exempt""" 
    def __init__(self, handler, authentication=None): 
     super(CsrfExemptResource, self).__init__(handler, authentication) 
     self.csrf_exempt = getattr(self.handler, 'csrf_exempt', True) 

La mia classe (frammento di codice) si presenta in questo modo:

user_resource = CsrfExemptResource(User) 

class User(BaseHandler): 
    allowed_methods = ('GET', 'POST', 'PUT', 'DELETE') 

    @require_extended 
    def create(self, request): 
     email = request.GET['email'] 
     password = request.GET['password'] 
     phoneNumber = request.GET['phoneNumber'] 
     firstName = request.GET['firstName'] 
     lastName = request.GET['lastName'] 
     self.createNewUser(self, email,password,phoneNumber,firstName,lastName) 
     return rc.CREATED 

prega fatemi sapere come si può ottengo il metodo di creazione per lavorare usando l'operazione POST?

+0

Ok, ho commentato "django.middleware.csrf.CsrfViewMiddleware" dal file delle impostazioni invece di utilizzare l'estensione di Classe di risorse. Vedo comunque il problema se – Cheezo

+0

Come stai tentando l'operazione HTTP "PUT" o "POST" che corrisponde a "crea" o "aggiorna"? Come sai che questo codice lato client sta creando una richiesta HTTP corretta e valida? –

+0

Per il POST, utilizzo un WizTools.org restclient dal quale posso creare esplicitamente una richiesta POST. Quindi sono sicuro che la richiesta sia passata e questo è sufficiente credo. – Cheezo

risposta

1

In utils.py, modificare questo.

def content_type(self): 
    """ 
    Returns the content type of the request in all cases where it is 
    different than a submitted form - application/x-www-form-urlencoded 
    """ 
    type_formencoded = "application/x-www-form-urlencoded" 

    ctype = self.request.META.get('CONTENT_TYPE', type_formencoded) 

    if ctype.strip().lower().find(type_formencoded) >= 0: 
     return None 

    return ctype 

https://bitbucket.org/jespern/django-piston/issue/87/split-charset-encoding-form-content-type

10

Ciò accade perché pistone non piace il fatto che ExtJS sta mettendo "charset = UTF-8" nel tipo di contenuto dell'intestazione.

facilmente fissato con l'aggiunta di un po 'di middleware per rendere il contenuto-tipo un po' più Pistone accogliente, creare un file chiamato middleware.py nell'applicazione directory di base:

class ContentTypeMiddleware(object): 

    def process_request(self, request): 
     if request.META['CONTENT_TYPE'] == 'application/x-www-form-urlencoded; charset=UTF-8': 
      request.META['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' 
     return None 

Poi semplicemente includere questo middleware nelle impostazioni .py:

MIDDLEWARE_CLASSES = (
    'appname.middleware.ContentTypeMiddleware', 
) 
7

soluzioni proposte ancora non ha funzionato per me (Django 1.2.3/pistone 0.2.2) così ho ottimizzato joekrell soluzione e questo finalmente funziona (sto usando solo POST e PUT, ma presumibilmente puoi aggiungere altri verbi alla lista):

class ContentTypeMiddleware(object): 

def process_request(self, request): 

    if request.method in ('POST', 'PUT'): 
     # dont break the multi-part headers ! 
     if not 'boundary=' in request.META['CONTENT_TYPE']: 
      del request.META['CONTENT_TYPE'] 

con:

MIDDLEWARE_CLASSES = (
'appname.middleware.ContentTypeMiddleware', 
) 

non ho notato alcun effetto collaterale, ma non posso promettere è a prova di proiettile.

+2

Sì, la soluzione ha funzionato anche per me (Django 1.3, Piston 0.2.2). In generale sembra che Piston sia diventato un abbandono, non è stato aggiornato da molto tempo. –

4

ho combinato qualcosa di quello che altre persone hanno detto, e aggiunto il supporto per qualsiasi tipo di contenuto, JSON per esempio ...

class ContentTypeMiddleware(object): 
    def process_request(self, request): 
     if request.method in ('POST', 'PUT') and request.META['CONTENT_TYPE'].count(";") > 0: 
      request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0] 
     return None 
+0

Questa è stata la soluzione migliore. Grazie. – GivP

+0

utilizzando questo per POST ha rotto altre cose, ma ha risolto i miei problemi quando si utilizzava solo per PUT –

4

ho pensato soluzione di Eric ha lavorato al meglio, ma poi corse in problemi durante il salvataggio cose in amministrazione Questo tweak sembra risolvere il problema se qualcun altro si imbatte in essa:

class ContentTypeMiddleware(object): 

    def process_request(self, request): 
     if request.method in ('POST') and not 'boundary=' in request.META['CONTENT_TYPE']: 
      request.META['CONTENT_TYPE'] = [c.strip() for c in request.META['CONTENT_TYPE'].split(";") ][0] 
     return None 
1

Questa è la soluzione che ha funzionato per me, dopo un tweak:

class ContentTypeMiddleware(object): 

    def process_request(self, request): 
     if 'charset=UTF-8' in request.META['CONTENT_TYPE']: 
      request.META['CONTENT_TYPE'] = request.META['CONTENT_TYPE'].replace('; charset=UTF-8','') 
     return None 
0

Abbiamo avuto una risorsa che è stato semplicemente aggiornando un timestamp basato sulla richiesta credenziali e PUT. Si scopre che Piston non ama PUT senza un carico utile. Aggiungendo un payload di stringa vuoto '' risolto.

Una rapida ricerca su Google indica che altri sistemi come Apache potrebbero non gradire PUT senza un payload.