2013-08-27 15 views
24

Piszę API REST i natknąłem się na problem. Jaki jest najlepszy sposób zwracania błędów sprawdzania poprawności.REST kody błędów powrotu funkcji API

Do tej pory byłem powrocie komunikaty o błędach po cenach dumpingowych na kod ogólny błąd (powiedzmy złe żądanie przykład)

{ 
    "status": 400, 
    "error": { 
     "code": 1, // General bad request code 
     "message": [ 
       "The Key \"a\" is missing", 
       "The Key \"b\" is missing", 
       "The Key \"c\" is missing", 
       "Incorrect Format for field \"y\"" 
     ] 
    } 

) 

ja zbadali trochę więcej o tym, jak powinien dobrą odpowiedzią API powinien wyglądać i pomyślałem z następujących opcji:

  1. zatrzymują się na pierwszym napotkanego błędu i zwróci odpowiedź z konkretnym kodem błędu

    { 
        "status": 400, //Same as the HTTP header returned 
        "error" { 
         "code": 1, // Specific field validation error code 
         "message": "Field \"x\" is missing from the array structure", 
         "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
         "more_info" => "www.api.com/help/errors/1" 
        } 
    ) 
    
  2. Parse wszystkie dane żądania i zwracać wiele błędów sprawdzania poprawności pola.

    { 
        "status": 400, 
        "error": { 
        "code": 1 //General bad Request code 
        "message": "Bad Request", 
        "developer_message": "Field validation errors." 
        "more_info": "www.api.com/help/errors/1", 
        "error_details": { 
          0: { 
            "code": 2 // Specific field validation error code 
            "message": "Field \"x\" is missing from the array structure", 
            "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
            "more_info": "www.api.com/help/errors/2" 
           }, 
    
          1: { 
            "code": 3 // Specific field validation error code 
            "message": "Incorrect Format for field \"y\"", 
            "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", 
            "more_info": "www.api.com/help/errors/3" 
           } 
            } 
         } 
        } 
    

Moim zdaniem opcja 2 byłaby właściwa droga (to daje więcej przydatnych informacji dla programistów/użytkowników końcowych i obciążenie serwera może być niższa (mniej wnioski/nie potrzeba revalidate poprawnych danych/nie trzeba obliczyć podpisu i uwierzytelnić użytkownika)), ale błądzę, jakie są najlepsze praktyki, a jeśli istnieje inny sposób leczenia tego rodzaju problemów.

Także myślę, że opcja 1 jest nadal ważna, jeśli ja dostać jeden poważny błąd w przepływie skryptu. (Nie błędy walidacji)

Należy pamiętać, że kod jest tylko prosta tablica tak jest łatwiej podążać. Format odpowiedzi to JSON lub XML.

+0

Chciałbym wiedzieć, czy ktokolwiek przeszedł # 2 i może mieć jakieś ulepszenia, więc otworzyłem nagrodę. – Ski

+0

Do czego służy ten interfejs API i jaki byłby cel komunikatów o błędach? Czy te wiadomości będą wyświetlane użytkownikowi końcowemu, czy nie? Ile żądań oczekuje na sekundę/minutę/dzień? Odpowiedź na twoje pytanie nie może być dokładna bez tych informacji. Nie masz odpowiedzi, ponieważ pytanie jest zbyt szerokie, to naprawdę zależy od użycia API. – skobaljic

Odpowiedz

0

Osobiście dałbym użytkownikom mniej szczegółów i albo błędy zrzutu potrzebne deweloperom w tabeli dzienników bazy danych, albo dziennikach systemowych. Z uwagi na to, że używasz JSON i jest to najczęściej na serwerach Apache, a Twój kod wygląda na php (ale twój przykład kodu z nawiasami klamrowymi może być liczbą języków pochodzących z PASCAL np. C, C# PERL, PHP, CSharp). Oto jak umieścić niestandardowe błędy wyjściowe w logach systemowych, jeśli jeszcze nie wiesz jak w php http://php.net/manual/en/function.syslog.php. Jeśli używasz rzadszej konfiguracji usług IIS z JSON i CSharp, istnieją biblioteki .NET, aby zrobić podobne. Jeśli podasz użytkownikom zbyt wiele informacji, gdy wystąpi błąd, dajesz hakerowi w przyszłości możliwość sprawdzenia witryny.

+0

Zakładam, że w tym scenariuszu, w przypadku, gdy dane są przekazywane z formularza wejściowego, weryfikacja musi być w pełni wykonana na interfejsie, a więc w przypadku, gdy niepoprawna wartość zostanie przekazana do backendu, zakładamy błąd w kodzie frontendu? – Ski

+0

Jeśli błąd w interfejsie użytkownika, w którym najbardziej nienawidzę, ponieważ jest odłączony, myślę o tym, czy asynchroniczny wpis Ajax do skryptu php serwera dzienników jest wart zachodu, tak naprawdę zależy od wagi błędu. Jeśli jest to coś trywialnego, możesz go wyświetlić użytkownikowi. Jeśli wystąpił błąd po stronie klienta, wówczas JSON może nawet nie być w równaniu. Mówisz teraz o czystych błędach JQuery lub JavaScript? Niepoprawne dane wejściowe zazwyczaj tylko pole wejściowe jest oświetlone na czerwono z komunikatem ogólnym. –

+0

W skrócie wszystko, co dzieje się po stronie klienta, można przesłać po stronie serwera z AJAX, odwiedzić facebook i użyć narzędzia o nazwie firebug i wybrać posty dotyczące aktywności na serwerze, a będziesz zaskoczony ilością postów wracających do serwera. Używam tego przykładu, ponieważ wciąż próbuję ustalić, jak ponownie otworzyć grupę na nim. To długa historia i nie mogę powiedzieć zbyt wiele. –

3

Użyłem parę # 2 kilka razy. Czy to lepsze niż pierwsze? Myślę, że to zależy od tego, do czego używane jest twoje API.

Lubię # 2, ponieważ daje programistom, który testuje API za pomocą niektórych wywołań testowych, szybki przegląd wszystkich błędów/błędów, które popełnił w żądaniu, dzięki czemu natychmiast wie, które błędy/błędy musi naprawić uczynić ten wniosek ważnym. Jeśli zwrócisz błędy jeden po drugim (jak w przypadku nr 1), musisz ciągle ponawiać prośbę i krzyżować palce, mając nadzieję, że tym razem będzie ona ważna.

Ale jak powiedziałem, numer 2 jest bardzo przydatny dla programistów, ale przyczyny nie mają zastosowania do użytkowników końcowych. Użytkownicy końcowi zwykle nie dbają o to, w jaki sposób jest zaimplementowany. Czy oprogramowanie wykonuje 1 żądanie, które zwraca 5 błędów lub 5 kolejnych żądań, które zwracają po 1 błędzie.
Dopóki jest dobrze obsługiwany przez klienta, użytkownik końcowy nie powinien zauważać różnicy. Jak sobie z tym poradzić, oczywiście zależy to od tego, czym naprawdę jest klient: , to jest.

Oprócz przyspieszenia rozwoju, kolejną zaletą # 2 (w produkcji) jest to, że wymaga mniejszej liczby żądań, co oczywiście zmniejsza obciążenie serwera.


I would like to know if anyone went #2 and maybe have any improvements on it so I opened a bounty.

Oczywiście istnieje możliwość dokonania ulepszeń. Tak jak to jest, niektóre dane w ciele można pominąć.

{ 
    "status": 400, 
    "error": { 
    "code": 1 //General bad Request code 
    "message": "Bad Request", 
    "developer_message": "Field validation errors." 
    "more_info": "www.api.com/help/errors/1", 
    "error_details": { 
      0: { 
        "code": 2 // Specific field validation error code 
        "message": "Field \"x\" is missing from the array structure", 
        "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
        "more_info": "www.api.com/help/errors/2" 
       }, 

      1: { 
       (
        "code": 3 // Specific field validation error code 
        "message": "Incorrect Format for field \"y\"", 
        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", 
        "more_info": "www.api.com/help/errors/3" 
       ) 
      } 
) 

Przy odpowiedziach HTTP kod statusu nie powinien znajdować się w treści, ale w nagłówku. Oznacza to, że tutaj można pominąć "status": 400 i "message": "Bad Request". 400 powinno być kodem statusu odpowiedzi, a 400 oznacza Złe żądanie. Jest to standard HTTP i nie trzeba go wyjaśniać w odpowiedzi. Również "developer_message": "Field validation errors." jest swego rodzaju duplikatem, ponieważ konkretne błędy są już zawarte w każdym oddzielnym błędzie, więc możemy to pominąć.

To pozostawia

{ 
    "error": { 
    "code": 1 //General bad Request code 
    "more_info": "www.api.com/help/errors/1", 
    "error_details": { 
      0: { 
        "code": 2 // Specific field validation error code 
        "message": "Field \"x\" is missing from the array structure", 
        "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
        "more_info": "www.api.com/help/errors/2" 
       }, 

      1: { 
       (
        "code": 3 // Specific field validation error code 
        "message": "Incorrect Format for field \"y\"", 
        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", 
        "more_info": "www.api.com/help/errors/3" 
       ) 
      } 
) 

"code": 1 //General bad Request code 
"more_info": "www.api.com/help/errors/1", 

te 2 linie naprawdę nie ma sensu już teraz. Oni także nie są wymagane, ponieważ każdy błąd ma swój własny kod i informacji łącza, więc możemy rozebrać te linie, jak również, pozostawiając to

{ 
    "error": { 
    "error_details": { 
      0: { 
        "code": 2 // Specific field validation error code 
        "message": "Field \"x\" is missing from the array structure", 
        "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
        "more_info": "www.api.com/help/errors/2" 
       }, 

      1: { 
       (
        "code": 3 // Specific field validation error code 
        "message": "Incorrect Format for field \"y\"", 
        "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", 
        "more_info": "www.api.com/help/errors/3" 
       ) 
      } 
) 

Kod 400 Stan już wskazuje, że wystąpił błąd, więc don” t muszą już oznaczać "error": {error details}, ponieważ wiemy już, że wystąpił błąd. Lista błędów może po prostu stać się głównym obiektem:

[ 
    { 
     "code": 2//Specificfieldvalidationerrorcode 
     "message": "Field \"x\" is missing from the array structure", 
     "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
     "more_info": "www.api.com/help/errors/2" 
    }, 
    { 
     "code": 3//Specificfieldvalidationerrorcode 
     "message": "Incorrect Format for field \"y\"", 
     "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"", 
     "more_info": "www.api.com/help/errors/3" 
    } 
] 

Wszystko, co pozostało w ciele, to po prostu lista błędów.

Kod statusu jest określony w nagłówku odpowiedzi.
Szczegóły są podane w treści odpowiedzi.

+1

Zgadzam się z opisanym podejściem: # 2 należy ulepszyć, aby uniknąć [redundancji danych] (http://en.wikipedia.org/wiki/Data_redundancy), więc może to być również niezgodność w statusie, jeśli pojawia się dwa razy. jest to powszechnie przyjęte przez wiele systemów obsługi wyjątków, na przykład: http: //www.asp.net/web-api/overview/error-handling/exception-handling –

0

Przede wszystkim zapewnilibyśmy klientom dokumentację metod API Rest API. Dlatego od klienta/dewelopera oczekuje się podania prawidłowych danych dla parametrów.

Teraz powiedziałem, że # 1 jest najlepszym sposobem na zrobienie Rest API. Odpowiedzialnością programisty jest ograniczenie wykorzystania serwera w maksymalnym możliwym stopniu. Jeśli wystąpi jakikolwiek błąd krytyczny, skonstruuj odpowiedź z odpowiednim kodem błędu i komunikatem o błędzie i zwróć ją.

Ponadto nie możemy być pewni, że po napotkanych błędach pojawi się więcej błędów. Nie ma sensu analizowanie pozostałych danych. Nie będzie dobrze działać, biorąc pod uwagę najgorszy przypadek.

+0

* Odpowiedzialnością programisty jest ograniczenie użycia serwera do maksimum w możliwym stopniu. * Ale jeśli zwrócisz błędy jeden po drugim (wymagające kolejnych wywołań), to tak naprawdę nie jest. –

16

Spójrzmy na Facebook's Graph API. To uderza mocno, a najprawdopodobniej generowanych jest wiele błędów. Oto co na Facebook zwraca błąd API:

{ 
    "error": { 
    "message": "Message describing the error", 
    "type": "OAuthException", 
    "code": 190, 
    "error_subcode": 460, 
    "error_user_title": "A title", 
    "error_user_msg": "A message" 
    } 
} 

starają się Graph API jak najbardziej użyteczna, ale wydają powrócić konkretnego błędu z kodem i kod pomocniczy (Ref). Fakt, że każdy błąd ma swój własny kod oznacza, że ​​łatwiej jest wyszukać wspomniany kod lub wiadomość jako punkt wyjścia do debugowania.Prawdopodobnie dlatego nie gromadzą komunikatów o błędach w oficjalnej odpowiedzi na błąd. Jeśli jest wystarczająco dobry i wygodny dla Facebooka, prawdopodobnie jest dla nas wystarczająco dobry.

Przykładowe błędach Odpowiedzi:

{ 
    "error": { 
    "message": "(#200) Must have a valid access_token to access this endpoint", 
    "type": "OAuthException", 
    "code": 200 
    } 
} 

i

"error": { 
    "message": "(#604) Your statement is not indexable. The WHERE clause must contain 
    an indexable column. Such columns are marked with * in the tables linked from 
    http://developers.facebook.com/docs/reference/fql ", 
    "type": "OAuthException", 
    "code": 604 
} 

Wtedy nie ma JSend który „jest specyfikacją, która ustanawia pewne zasady na jak odpowiedzi JSON z serwerów internetowych powinny być sformatowane. " Ich celem jest:

There are lots of web services out there providing JSON data, and each has its own way of formatting responses. Also, developers writing for JavaScript front-ends continually re-invent the wheel on communicating data from their servers. While there are many common patterns for structuring this data, there is no consistency in things like naming or types of responses. Also, this helps promote happiness and unity between backend developers and frontend designers, as everyone can come to expect a common approach to interacting with one another.

Oto przykładowy komunikat o błędzie:

{ 
    "status" : "fail", 
    "data" : { "title" : "A title is required" } 
} 

Wygląda jak Facebook i ta grupa próbuje ustawić jak standard przemysłowy decyduje do wyboru # 1.


Bounty Pytanie

W odpowiedzi na wniosek laska "jeśli ktoś poszedł # 2, a może ma jakieś ulepszenia na to?", Istnieje wzorzec projektowania z Pragmatic RESTful API który stwierdza:

Validation errors will need a field breakdown. This is best modeled by using a fixed top-level error code for validation failures and providing the detailed errors in an additional errors field, like so:

{ 
    "code" : 1024, 
    "message" : "Validation Failed", 
    "errors" : [ 
    { 
     "code" : 5432, 
     "field" : "first_name", 
     "message" : "First name cannot have fancy characters" 
    }, 
    { 
     "code" : 5622, 
     "field" : "password", 
     "message" : "Password cannot be blank" 
    } 
    ] 
} 
1

Niedawno pracowałem przeciwko interfejsowi API Rest, który zwróciłby wiele ostrzeżeń lub błędów w wynikach. Począwszy od próbka nr 2, bym go zmodyfikować w następujący sposób:

{ 
    "status": 400, 
    "results" : null, 
    "warnings": { 
     0: { 
       // Build a warning message here, sample text to show concept 
       "code": 1 // Specific field validation error code 
       "message": "It is no longer neccessary to put .js on the URL" 
      } 
    } 
    "errors": { 
     0: { 
       "code": 2 // Specific field validation error code 
       "message": "Field \"x\" is missing from the array structure" 
       "developer_message": "The request structure must contain the following fields {a,b,c{x,y,z}}", 
      }, 
     1: { 
       "code": 3 // Specific field validation error code 
       "message": "Incorrect Format for field \"y\"", 
       "developer_message": "The field \"y\" must be in the form of \"Y-m-d\"" 
      } 
     } 
    } 

Byłoby to zapewnić możliwość dostarczenia wyników z wielu ostrzeżeń lub błędów jako niezbędnych w swojej odpowiedzi.

I tak, to ma pewne rozrost w strukturze, ale zapewnia również łatwy interfejs dla programisty, aby zawsze odzyskać dane w tej samej strukturze.

Chciałbym również usunąć następujące elementy jak IMHO powinny one być w docs API (jak szukać pomocy za pomocą kodu błędu) zamiast na każdym błędzie:

"more_info": "www.api.com/help/errors/2" 
"more_info": "www.api.com/help/errors/3" 

wzdłuż tych samych linii, I” m nie jestem pewien, czy potrzebujesz zarówno wiadomości, jak i wersji dla programistów. Wydaje się, że są zbędne i próbują przekazać komunikaty o błędach użytkownika z interfejsu API, gdy osoba dzwoniąca nie podała poprawnych danych.

1

Interfejsy API nie są przeznaczone dla ludzi. Dlatego nie trzeba zwracać szczegółowych komunikatów o błędach. Możesz nawet zwrócić kod błędu, który oznacza "brakujący parametr". Tylko nie zapomnij udokumentować tego dobrze.

+0

Interfejsy API są również dla ludzi, programista używający API to człowiek. Poza tym, może komunikaty o błędach muszą być przekazywane bezpośrednio do użytkownika końcowego. –