2012-12-08 9 views
5

wyjątki zwrócone w HTML łamią mojego klienta JSON. Chcę jsonifikować to wyjście.API w kolbie - zwraca JSON, ale wyjątki HTML łamią mojego klienta JSON

Więcej szczegółów: Mam funkcję widoku, która jest punktem końcowym tej aplikacji api.

Jak widać, ta funkcja zwraca wynik w json.

@app.route('/route1') 
def api_route1(): 
    if user_id in request.args: 
     k1 = request.args['user_id'] 
     return flask.jsonify(recs=some_function(k1)) 
    else: 
     return "no valid user_id supplied" 

Problem nieobsługiwany wyjątek są w HTML, na przykład,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
    Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
    <head> 
     <title>TypeError: 'NoneType' object is not iterable // Werkzeug Debugger</title> 
     <link rel="stylesheet" 
      href="?__debugger__=yes&amp;cmd=resource&amp;f=style.css" 
      type="text/css"> 

To łamie mój klient JSON. Format HTML jest niewątpliwie domyślny, ale nie wiem, jak go wyłączyć i określić jsonowane wyjątki (i idealnie jsonować wszystko zwracane nawet nagłówki).

Podejrzewam, że to, czego potrzebuję, znajduje się w doskonałej dokumentacji Flask, ale nie mogę go znaleźć.

+0

Próbujesz zachować komunikaty o błędach i wysłać je jako JSON na wypadek, gdyby coś poszło nie tak? – Blender

+0

@Blender, tak, właśnie tego chcę. – doug

Odpowiedz

4

Udostępnienie funkcji traceback do klienta JSON może ujawnić poufne informacje.

Moja rada brzmi:

  • kolej debug off
  • zainstalować narzędzie agregacji dziennika jak sentry
  • sprawiają, że błąd 500 strona dla tej aplikacji powrócić ogólny błąd w formacie JSON

Strona 500 może wyglądać następująco:

{ "error": "500 - internal server error" } 
+0

Tak powinien zrobić PO. – sberry

1

Poniższy kod powinien wystarczyć. Chodzi o to, aby wychwycić każdy wyjątek, który mógł zostać podniesiony, uzyskać szczegóły wyjątku sformatowane jako ciąg znaków za pomocą modułu traceback, a następnie zwrócić go jako prawidłowy json. Poleciłbym wstawić kilka wyjątków z głównymi typami błędów, które mogą się wydarzyć, oraz bardziej czytelnym komunikatem o błędzie. W takim razie możesz mieć jedną ostatnią, chyba że jako haczyk na wypadek, gdyby wydarzyło się coś dziwnego i nieoczekiwanego.

import traceback 

@app.route('/route1') 
def api_route1(): 
    if user_id in request.args: 
     try: 
      k1 = request.args['user_id'] 
      return flask.jsonify(recs=some_function(k1)) 
     except: 
      return flask.jsonify(exception=traceback.format_exc()) 
    else: 
     return flask.jsonify(exception="no valid user_id supplied") 
+0

Nawet część else może mieć jsonify, to znowu zwróci html, gdy id_użytkownika nie ma argumentów. – Codeanu

+0

@ Codeanu dobra sugestia, zaktualizowałem odpowiedź z tym, co sugerujesz. –

6

Należy określić HTTP error handlers in flask.

Prosty JSON returing 404 obsługi może wyglądać mniej więcej tak:

@app.errorhandler(404) 
def page_not_found(e): 
    return flask.jsonify(error=404, text=str(e)), 404 

Z tego będzie można sprawdzić na data.error na kliencie i jeśli istnieje cię można uzyskać tekst błędu za pomocą danych.tekst (błąd przekazany jako e jest werkzeug.exceptions.NotFound, którego reprezentacja ciągów to "404: Nie znaleziono").