Bilag 2 - Fejlstruktur og fejlkoder for REST webservices

Body: 

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. afsnit 3.7 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.

Afsnit 1 indeholder indledning, beskrivelse af målgruppe samt afgrænsninger.

Afsnit 2indeholder retningslinjer for fejlmeddelelse af REST webservices. Her beskrives, hvorledes HTTP statuskoder anvendes og giver konkret indhold af fejlstrukturer, der returneres til serviceanvendere.

Afsnit 3beskriver det konkrete indhold af HTTP headeren ved fejl og anvendelsen af HTTP statuskoder.

Afsnit 4beskriver den generelle fejlstruktur for fejlmeddelelser, som kan sendes på tværs af protokoller, herunder konkrete eksempler i JSON, XML og CSV.

Afsnit 5indeholder 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 afsnit 4.

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. afsnit 4.

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, jf. afsnit 4.4.

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 i afsnit 2.1kan 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-bb3106f5227d”.

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”, version 0.9. 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:

Tabel 1 Liste over HTTP-statuskoder

Value

Description

Reference

100

Continue

[RFC7231, Section 6.2.1]

101

Switching Protocols

[RFC7231, Section 6.2.2]

102

Processing

[RFC2518]

103-199

Unassigned

 

200

OK

[RFC7231, Section 6.3.1]

201

Created

[RFC7231, Section 6.3.2]

202

Accepted

[RFC7231, Section 6.3.3]

203

Non-Authoritative Information

[RFC7231, Section 6.3.4]

204

No Content

[RFC7231, Section 6.3.5]

205

Reset Content

[RFC7231, Section 6.3.6]

206

Partial Content

[RFC7233, Section 4.1]

207

Multi-Status

[RFC4918]

208

Already Reported

[RFC5842]

209-225

Unassigned

 

226

IM Used

[RFC3229]

227-299

Unassigned

 

300

Multiple Choices

[RFC7231, Section 6.4.1]

301

Moved Permanently

[RFC7231, Section 6.4.2]

302

Found

[RFC7231, Section 6.4.3]

303

See Other

[RFC7231, Section 6.4.4]

304

Not Modified

[RFC7232, Section 4.1]

305

Use Proxy

[RFC7231, Section 6.4.5]

306

(Unused)

[RFC7231, Section 6.4.6]

307

Temporary Redirect

[RFC7231, Section 6.4.7]

308

Permanent Redirect

[RFC7538]

309-399

Unassigned

 

400

Bad Request

[RFC7231, Section 6.5.1]

401

Unauthorized

[RFC7235, Section 3.1]

402

Payment Required

[RFC7231, Section 6.5.2]

403

Forbidden

[RFC7231, Section 6.5.3]

404

Not Found

[RFC7231, Section 6.5.4]

405

Method Not Allowed

[RFC7231, Section 6.5.5]

406

Not Acceptable

[RFC7231, Section 6.5.6]

407

Proxy Authentication Required

[RFC7235, Section 3.2]

408

Request Timeout

[RFC7231, Section 6.5.7]

409

Conflict

[RFC7231, Section 6.5.8]

410

Gone

[RFC7231, Section 6.5.9]

411

Length Required

[RFC7231, Section 6.5.10]

412

Precondition Failed

[RFC7232, Section 4.2] [RFC8144, Section 3.2]

413

Payload Too Large

[RFC7231, Section 6.5.11]

414

URI Too Long

[RFC7231, Section 6.5.12]

415

Unsupported Media Type

[RFC7231, Section 6.5.13] [RFC7694, Section 3]

416

Range Not Satisfiable

[RFC7233, Section 4.4]

417

Expectation Failed

[RFC7231, Section 6.5.14]

418-420

Unassigned

 

421

Misdirected Request

[RFC7540, Section 9.1.2]

422

Unprocessable Entity

[RFC4918]

423

Locked

[RFC4918]

424

Failed Dependency

[RFC4918]

425

Unassigned

 

426

Upgrade Required

[RFC7231, Section 6.5.15]

427

Unassigned

 

428

Precondition Required

[RFC6585]

429

Too Many Requests

[RFC6585]

430

Unassigned

 

431

Request Header Fields Too Large

[RFC6585]

432-450

Unassigned

 

451

Unavailable For Legal Reasons

[RFC7725]

452-499

Unassigned

 

500

Internal Server Error

[RFC7231, Section 6.6.1]

501

Not Implemented

[RFC7231, Section 6.6.2]

502

Bad Gateway

[RFC7231, Section 6.6.3]

503

Service Unavailable

[RFC7231, Section 6.6.4]

504

Gateway Timeout

[RFC7231, Section 6.6.5]

505

HTTP Version Not Supported

[RFC7231, Section 6.6.6]

506

Variant Also Negotiates

[RFC2295]

507

Insufficient Storage

[RFC4918]

508

Loop Detected

[RFC5842]

509

Unassigned

 

510

Not Extended

[RFC2774]

511

Network Authentication Required

[RFC6585]

512-599

Unassigned