Dette dokument beskriver, hvordan fejl skal håndteres i REST webservices. Dokumentet er bilag 2 til fællesoffentlige retningslinjer for webservices, beskrevet i ”Fælles retningslinjer for REST webservices” [WEBSER] og er en konkretisering af fejlmeddelelse, jf. afsnittet Servicefejlmeddelelser i [WEBSER].
Dokumentet beskriver hvorledes en struktureret fejlmeddelelse på tværs af myndigheders webservices giver større interoperabilitet, idet serviceanvendere af webservices får et mere genkendeligt og homogent it-landskab.
Den strukturerede fejlmeddelelse fastlægger:
- Anvendelse af fejlstrukturer på tværs af protokoller og integrationsmønstre.
- Fejlmeddelelse for REST webservices der anvender HTTP ved kald
- Beskrivelse af serviceudstilleres og serviceanvenderes ansvar
- Ensartede fejlstrukturer, som definerer syntaks for fejlbeskeder
- Brug af forståelige fejlbeskeder, der sikrer, at der kan gives forståelige fejlbeskeder til både it-systemer og slutbrugere
Dette dokument beskriver ikke, hvorledes services monitoreres og forvaltes.
Nærværende afsnit indeholder indledning, beskrivelse af målgruppe samt afgrænsninger.
Det følgende afsnit ndeholder retningslinjer for fejlmeddelelse af REST webservices. Her beskrives, hvorledes HTTP statuskoder anvendes og giver konkret indhold af fejlstrukturer, der returneres til serviceanvendere.
Derefter beskrives det konkrete indhold af HTTP headeren ved fejl og anvendelsen af HTTP statuskoder.
Efterfølgende beskrives den generelle fejlstruktur for fejlmeddelelser, som kan sendes på tværs af protokoller, herunder konkrete eksempler i JSON, XML og CSV.
Til sidst angives en liste over anvendte referencer.
Målgruppe
Målgruppen for læsere af dette dokument er:
- IT-Arkitekter og udviklere for serviceudstillere, som ønsker at udstille en webservice med en fejlmeddelelse, som overholder de fællesoffentlige retningslinjer.
- IT-Arkitekter og udviklere for serviceanvendere, som ønsker at anvende en webservice med en fejlmeddelelse, som overholder de fællesoffentlige retningslinjer.
Fejlmeddelelser i REST webservices
REST webservices anvender HTTP som kommunikationsprotokol, og indikerer overfor serviceanvendere at en fejl er opstået ved at overføre en statuskode i header. Tilsvarende er det best-practice at medsende en struktureret fejl i body af et HTTP response.
Statuskoder med tilhørende tekst har en værdi inden for et bestemt udfaldsrum, som er angivet i standarden. Statuskoder er en endelig liste defineret i sektion 10 af [RFC2616]. Statuskoder er en liste over både meget konkrete fejlkoder og mere generelle fejlkoder, hvor udfaldsrummet for statuskoder er angivet i RFC 7231, jf. Appendiks A. I REST og HTTP-standarden er det således op til serviceudstiller at afgøre, hvilke applikationsfejl, der modsvarer de enkelte HTTP statuskoder.
For at skabe mere ensartede snitflader for serviceanvendere præciserer retningslinjerne, hvorledes applikationsfejl udstilles.
Serviceanvenderen skal se information i statuskoder i kombination med fejlstrukturer medsendt i body. Fejlstruktur i body giver mulighed for en mere nuanceret fejlbeskrivelse, fx med et fast skema som angiver syntaks og semantik. Fejlstrukturer defineret i skemaer muliggør anvendelse af samme fejlstruktur på tværs af protokoller, fx SOAP eller FTP. Strukturen for fejlmeddelelser er beskrevet yderligere i afsnittet 'Struktur for REST fejlmeddelelse i header'.
Statuskoder er beskrevet af HTTP protokollen, som vedligeholdes af IANA og præciserer anvendelsen, jf. appendiks A. Det er op til serviceudstiller at træffe designbeslutning om, hvilke statuskoder der anvendes til de applikationsfejl, som er mulige i den enkelte service. Den designbeslutning er situationsafhængig og kan være svær at ensrette på tværs af webservices. Retningslinjerne har derfor ikke specifikke retningslinjer for, hvorledes applikationsfejl udstilles.
En REST webservice skal dog altid overholde følgende generelle design til returnering af statuskoder:
- 2xx: Success – Statuskoder med 2xx angiver at kaldet var en succes (blev gennemført).
- 4xx: Client Error – Statuskoder med 4xx skyldes en fejl, som serviceanvender har ansvaret for.
- 5xx: Server Error - Statuskoder med 4xx skyldes en fejl, som serviceudstiller har ansvaret for.
Indholdet af tekstfeltet i HTTP-statusfeltet kan anvendes frit af serviceudstiller, men mange services anvender som best-practice standardteksten til den tilhørende fejlkode. Standardteksten er angivet i ”description” kolonnen i Appendiks A. Retningslinjerne vil følge denne metode og angive standardteksten fra IANA. Fejlmeddelelser i body fra webservice skal angives i en fejlstruktur, jf. afsnittet 'Struktur for REST fejlmeddelelse i header'.
Håndtering af fejl i backend-systemer
Det er en udbredt løsning i det offentlige it-landskab, at CRUD operationer sker asynkront. Dette afsnit beskriver, hvorledes serviceanvendere kan få en asynkron kvittering fra et backend-system ved anvendelse af en REST webservice. Der er således både en teknisk kvittering, som er synkron (response/request), og en asynkron forretningskvittering.
Eksempel på brugsscenarie:
Webservicen står i en demilitariseret zone (DMZ) og persisterer data midlertidigt i en kø eller tilsvarende, som efterfølgende loades ind i et backend-system. Her kan webservicen i DMZ kun tjekke syntaks og semantik som angivet i snitfladen, men kan ikke håndtere forretningsregler som håndhæves i backend-systemet. En forretningsregel kan fx være: ”serviceanvender ønsker at journalisere et dokument på en sag, men sagen findes ikke i backend-systemet, hvilket giver en fejl.”
En del HTTP-metoder har dog ikke et body i response, når det er et succesfuldt synkront kald. Derfor tillader HTTP ikke, at der medsendes en mere detaljeret body om, hvordan status på forretningskvittering fremskaffes. Det gælder følgende metoder:
- PUT
- PATCH
- DELETE
PUT-metoden skal anvendes ved oprettelse og opdatering af en ressource ved angivelse af et id, POST kan oprette en ressource uden et id, jf. [Bilag 4] ” Specifikation for brug af HTTP til REST” til [WEBSER]. Et kald med PUT eller POST til en REST ressource kan umiddelbart have to relevante resultater:
- Data er modtaget og ressourcen i it-systemet er opdateret. I det tilfælde skal en webservice returnere HTTP statuskode 201 for at kunne overholde retningslinjerne.
- Data er modtaget og ressourcen i et bagvedliggende it-system (backend-systemet) er ikke opdateret. Webservicen returnerer HTTP-statuskode 202 med en custom header kaldet X-Progress med en URI, hvor status på kaldet efterfølgende kan hentes med en GET request. I GET response fremgår forretningskvitteringen med status på processen.
Såfremt processen resulterer i en efterfølgende fejl fra backend-systemet, er det serviceanvenders ansvar at håndtere fejlen.
Tilsvarende gælder for DELETE, dog returneres HTTP-statuskode 200 ved succes i stedet for HTTP-statuskode 201.
Retningslinjerne omfatter ikke præciseringer for PATCH på dette område.
Struktur for REST fejlmeddelelse i header
Dette afsnit indeholder beskrivelse af udformning af HTTP headers i forbindelse med fejlmeddelelse. Øvrige krav til HTTP headers som operationelle parametre beskrives i [Bilag 4] ” Specifikation for brug af HTTP til REST”.
I det følgende beskrives HTTP headers for HTTP request (kald) og HTTP response (svar) i forskellige afsnit, da der er forskellige krav til brug af headere.
Request headers
Serviceanvenderen skal inkludere HTTP headeren ”Accept-Language” for at angive foretrukket sprog. Såfremt der opstår en fejl i den udstillede service, skal brugervendte fejlmeddelelser være på det angivne sprog, hvis det er muligt. Hvis serviceanvender ikke har angivet sprog, så skal brugervendte fejlmeddelelser returneres på dansk.
Serviceanvendere skal inkludere HTTP headeren ”If-Match” i PUT-metoder, hvis serviceanvender ønsker en fejl fra serviceudstiller, hvis den angivne ressource ikke er ændret, siden den sidst var blevet opdateret af serviceanvender. Det kan forhindre overskrivninger i ressourcer (”race conditions”) ved samtidige opdateringer af hele ressourcer.
Response headers
I tilfælde af en fejl skal REST webservices returnere følgende header felter:
- ”Last-Modified”: dato for ressourcens sidste opdateringsdato skal returneres ved fejl i PUT-metoder.
- ”Content-Language”: er en specifikation af sproget i fejlmeddelelsen.
- Statusline, indeholder statuskode og fejlteksten i formatet: ”HTTP-Version SP Status-Code SP Reason-Phrase CRLF”.
Struktur for fejlmeddelelser i generelle webservices
Strukturen for generelle fejlmeddelelser anvendes mellem webservices på tværs af grænser mellem services, derfor må fejlmeddelelser ikke indeholde interne fejlkoder, fx stacktrace.
Fejlmeddelelsen håndterer både fejl fra et kald, som vedrører en enkelt ressource, eller kald som vedrører en kollektion af ressourcer. Fx hvis en operation opdaterer 100 sager, og der er tre som fejler, så skal der returneres en sigende fejl per sag.
Fejlmeddelelser skal returneres i UTF-8 encoding.
Fejlmeddelelsen skal indeholde følgende:
Feltnavn |
Forklaring |
---|---|
Statuskode |
Statuskode skal være værdien svarende til HTTP-statuskoden. |
Ressource-id |
Ressource-id angiver den ressource, som fejlen omhandler. Såfremt der er tale om en generel fejl i webservicen, skal feltet være tomt. |
Transaktionsidentifikator |
Kaldets transaktionsidentifikator skal medsendes jf. R14 i [WEBSER]. |
Indkomne registrerede parametre |
Webservicens indgående parametre, undtagen evt. binært indhold, skal inkluderes i fejlbeskrivelsen. |
Fejlkode |
Webservicens fejlkode som svarer til en fejlkode i dokumentationen. Fejlkoden vil typisk være fra en mere detaljeret liste end statuskode. |
Systemfejlbeskrivelse, |
Teksten skal indeholde så mange relevante detaljer for serviceanvender som muligt, dog under hensyntagen til at undgå store fejlmeddelelser grundet båndbreddeforbrug, samt hensyn til sikkerhedskrav og krav om informationers følsomhed og fortrolighed. |
Brugervendt fejlbeskrivelse |
Webservicen skal returnere en brugervendt fejlbeskrivelse på et bestemt sprog, som angivet af serviceanvender, eller på dansk, såfremt serviceanvender ikke har angivet et sprog, eller såfremt webservicen ikke returnerer fejlbeskrivelsen på det ønskede sprog. |
Link til dokumentation |
Link til dokumentation er en http:uri til dokumentation af fejlen. |
Eksempel JSON
Nedenstående viser et eksempel på en JSON implementering af den generelle fejlmeddelelse: En REST webservice, som returnerer JSON, skal returnere følgende struktur for at overholde retningslinjerne ved fejl:
{
"Status" : ”418”,
”Ressourceid” : ”4Ab7b763-8213-4c85-aa2e-bb3106f5227d”
”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”,
"Parameters" : [123,456,ABC],
"ErrorCode" : 444444,
”ErrorDesciption” : ”parameter is not numeric”,
”UserDesciption” : ”Værdien ABC er ikke et tal”,
"MoreInfo" : ”http://www.genstand.com/help/v2/swagger.json” }
Eksempel XML
Nedenstående viser et eksempel på en JSON implementering af den generelle fejlmeddelelse: En REST webservice, som returnerer XML, skal returnere følgende struktur for at overholde retningslinjerne ved fejl:
<Errormessage>
<Status>418</status>
<”Ressourceid>4Ab7b763-8213-4c85-aa2e-bb3106f5227</Ressouceid>
<Transactionid>34b7b763-8213-4c85-aa2e-bb3106f5227d</Transactionid>
<Parameters><Parameter>123</Parameter><Parameter>456</Parameter><Parameter>ABC</Parameter>
<ErrorCode> 444444 <ErrorCode>
<ErrorDesciption>parameter is not numeric<ErrorDescription>
<UserDesciption>Værdien ABC er ikke et tal</UserDesciption>
<MoreInfo>[CDATA[[http://www.genstand.com/help/v2/swagger.json]]</MoreInfo>
Eksempel CSV(Batch)
Errorline:
”418”, 4Ab7b763-8213-4c85-aa2e-bb3106f5227d, ”34b7b763-8213-4c85-aa2e-bb3106f5227d”, ”[123,456,ABC]”, ”444444”, ”parameter is not numeric”, ”Værdien ABC er ikke et tal”, ”http://www.genstand.com/help/v2/swagger.json”
Eksempel Status request JSON
Som beskrevet ovenfor, kan en asynkron service medføre, at en serviceanvender må forespørge en statusservice, som returnerer status for en given asynkron transaktion. En URL angives af service udstiller i header, fx: Get eksempel URL: ”http://www.genstand.com/Geonoegler/status/34b7b763-8213-4c85-aa2e-bb3106...”.
Nedenstående viser et eksempel på en JSON implementering af den request og response for en statusmeddelelse:
GET JSON Request:
{”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”}
En REST webservice, som returnerer XML, skal returnere følgende struktur for at overholde retningslinjerne ved fejl:
GET JSON Response har en status, som har udfaldsrummet Accepted, OK, Failed:
{”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”, ”Pro-gress”: ”Accepted” ”Retry-After”: ”1000”}
{”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”, ”Pro-gress”: ”OK” }
{”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”,
”Progress”: ”Failed”,
"Status" : ”418”,
”Transactionid” : ” 34b7b763-8213-4c85-aa2e-bb3106f5227d”,
"Parameters" : [123,456,ABC],
"ErrorCode" : 444444,
”ErrorDesciption” : ”parameter is not numeric”,
”UserDesciption” : ”Værdien ABC er ikke et tal”,
"MoreInfo" : ”http://www.genstand.com/help/v2/swagger.json”
}
Kilder
ID |
Kilde |
|
---|---|---|
[BILAG 1] |
Bilag 1 ”Dokumentation for REST webservices” til [WEBSER] |
|
[BILAG 3] |
Bilag 3 ”Nonfunktionelle krav til realisering af retningslinjer” |
|
[BILAG 4] |
Bilag 4 ” Specifikation for brug af HTTP til REST” til [WEBSER] |
|
[WEBSER] |
Digitaliseringsstyrelsen (2017) Fælles retningslinjer for REST webservices”. Tilgængelig på: https://arkitektur.digst.dk/metoder/retningslinjer-webservices |
|
[HTTP] |
Hypertext Transfer Protocol (HTTP/1.1), RFC 7230, 7231, 7232, 7233, 7234, 7235. |
|
[FIELDING] |
Roy Fielding (2000) Architectural Styles and the Design of Network-based Software Architectures. Tilgængelig på: https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm |
|
[RFC2616] |
RFC 2616 https://www.ietf.org/rfc/rfc2616.txt |
Appendiks A. - HTTP Status koder
Listen over HTTP-statuskoder vedligeholdes af IANA og er per oktober 2017:
Value |
Description |
Reference |
---|---|---|
100 |
Continue |
|
101 |
Switching Protocols |
|
102 |
Processing |
|
103-199 |
Unassigned |
|
200 |
OK |
|
201 |
Created |
|
202 |
Accepted |
|
203 |
Non-Authoritative Information |
|
204 |
No Content |
|
205 |
Reset Content |
|
206 |
Partial Content |
|
207 |
Multi-Status |
|
208 |
Already Reported |
|
209-225 |
Unassigned |
|
226 |
IM Used |
|
227-299 |
Unassigned |
|
300 |
Multiple Choices |
|
301 |
Moved Permanently |
|
302 |
Found |
|
303 |
See Other |
|
304 |
Not Modified |
|
305 |
Use Proxy |
|
306 |
(Unused) |
|
307 |
Temporary Redirect |
|
308 |
Permanent Redirect |
|
309-399 |
Unassigned |
|
400 |
Bad Request |
|
401 |
Unauthorized |
|
402 |
Payment Required |
|
403 |
Forbidden |
|
404 |
Not Found |
|
405 |
Method Not Allowed |
|
406 |
Not Acceptable |
|
407 |
Proxy Authentication Required |
|
408 |
Request Timeout |
|
409 |
Conflict |
|
410 |
Gone |
|
411 |
Length Required |
|
412 |
Precondition Failed |
[RFC7232, Section 4.2] [RFC8144, Section 3.2] |
413 |
Payload Too Large |
|
414 |
URI Too Long |
|
415 |
Unsupported Media Type |
[RFC7231, Section 6.5.13] [RFC7694, Section 3] |
416 |
Range Not Satisfiable |
|
417 |
Expectation Failed |
|
418-420 |
Unassigned |
|
421 |
Misdirected Request |
|
422 |
Unprocessable Entity |
|
423 |
Locked |
|
424 |
Failed Dependency |
|
425 |
Unassigned |
|
426 |
Upgrade Required |
|
427 |
Unassigned |
|
428 |
Precondition Required |
|
429 |
Too Many Requests |
|
430 |
Unassigned |
|
431 |
Request Header Fields Too Large |
|
432-450 |
Unassigned |
|
451 |
Unavailable For Legal Reasons |
|
452-499 |
Unassigned |
|
500 |
Internal Server Error |
|
501 |
Not Implemented |
|
502 |
Bad Gateway |
|
503 |
Service Unavailable |
|
504 |
Gateway Timeout |
|
505 |
HTTP Version Not Supported |
|
506 |
Variant Also Negotiates |
|
507 |
Insufficient Storage |
|
508 |
Loop Detected |
|
509 |
Unassigned |
|
510 |
Not Extended |
|
511 |
Network Authentication Required |
|
512-599 |
Unassigned |
|