Hvad er RESTful-programmering egentlig?

Hvad er RESTful-programmering egentlig?

REST er det underliggende arkitektoniske princip for internettet. Det fantastiske ved internettet er, at klienter (browsere) og servere kan interagere på komplekse måder, uden at klienten på forhånd kender noget som helst til serveren og de ressourcer, den er vært for. Den vigtigste begrænsning er, at serveren og klienten begge skal være enige om de medier, der anvendes, hvilket i web-sagen er HTML.

En API, der følger principperne i REST, kræver ikke, at klienten kender noget som helst til API'ens struktur. Serveren skal snarere levere de oplysninger, som klienten har brug for for at kunne interagere med tjenesten. En HTML-formular er et eksempel herpå: Serveren angiver ressourcens placering og de nødvendige felter. Browseren ved ikke på forhånd, hvor den skal indsende oplysningerne, og den ved ikke på forhånd, hvilke oplysninger den skal indsende. Begge former for information leveres udelukkende af serveren (Dette princip kaldes [HATEOAS: Hypermedia As The Engine Of Application State] (https://en.wikipedia.org/wiki/HATEOAS).)

Hvorledes gælder dette for HTTP, og hvordan kan det gennemføres i praksis? HTTP er orienteret omkring verber og ressourcer. De to verber i almindelig brug er GET og POST, som jeg tror alle vil genkende. HTTP-standarden definerer imidlertid flere andre, f.eks. PUT og DELETE. Disse verber anvendes så på ressourcer i overensstemmelse med de instruktioner, som serveren giver.

Lad os f.eks. forestille os, at vi har en brugerdatabase, som administreres af en webtjeneste. Vores tjeneste bruger et brugerdefineret hypermedie baseret på JSON, som vi tildeler mimetype application/json+userdb (der kan også være en application/xml+userdb og application/whatever+userdb - mange medietyper kan understøttes). Klienten og serveren er begge programmeret til at forstå dette format, men de ved ikke noget om hinanden. Som Roy Fielding påpeger:

En REST API bør bruge næsten al sin beskrivende indsats på at definere den eller de medietyper, der anvendes til at repræsentere ressourcer og styre applikationstilstand, eller til at definere udvidede relationsnavne og/eller hypertekst-aktiveret mark-up for eksisterende standardmedietyper.

En forespørgsel efter basisressourcen / kan give noget i denne retning:

Request

GET /
Accept: application/json+userdb

Response

200 OK
Content-Type: application/json+userdb

{
    "version": "1.0",
    "links": [
        {
            "href": "/user",
            "rel": "list",
            "method": "GET"
        },
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

Vi ved fra beskrivelsen af vores medie, at vi kan finde oplysninger om relaterede ressourcer i sektioner kaldet "links". Dette kaldes Hypermedia-kontroller. I dette tilfælde kan vi fra et sådant afsnit se, at vi kan finde en brugerliste ved at lave en anden forespørgsel efter /user:

Request

GET /user
Accept: application/json+userdb

Response

200 OK
Content-Type: application/json+userdb

{
    "users": [
        {
            "id": 1,
            "name": "Emil",
            "country: "Sweden",
            "links": [
                {
                    "href": "/user/1",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/1",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/1",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        },
        {
            "id": 2,
            "name": "Adam",
            "country: "Scotland",
            "links": [
                {
                    "href": "/user/2",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/2",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/2",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        }
    ],
    "links": [
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

Vi kan se meget af dette svar. For eksempel ved vi nu, at vi kan oprette en ny bruger ved at POSTing til /user:

Request

POST /user
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Karl",
    "country": "Austria"
}

Response

201 Created
Content-Type: application/json+userdb

{
    "user": {
        "id": 3,
        "name": "Karl",
        "country": "Austria",
        "links": [
            {
                "href": "/user/3",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/3",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/3",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

Vi ved også, at vi kan ændre eksisterende data:

Anmodning

PUT /user/1
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Emil",
    "country": "Bhutan"
}

Response

200 OK
Content-Type: application/json+userdb

{
    "user": {
        "id": 1,
        "name": "Emil",
        "country": "Bhutan",
        "links": [
            {
                "href": "/user/1",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/1",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/1",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

Bemærk, at vi bruger forskellige HTTP-verber (GET, PUT, POST, DELETE osv.) til at manipulere disse ressourcer, og at den eneste viden, vi forudsætter fra klientens side, er vores mediedeklaration.

Yderligere læsning:

(Dette svar har været genstand for en del kritik, fordi det ikke har forstået pointen. For det meste har det været en rimelig kritik. Det, jeg oprindeligt beskrev, var mere i overensstemmelse med, hvordan REST normalt blev implementeret for et par år siden, da jeg først skrev dette, end med dets egentlige betydning. Jeg'har revideret svaret for bedre at repræsentere den reelle betydning).

Kommentarer (39)

REST bruger de forskellige HTTP-metoder (primært GET/PUT/DELETE) til at manipulere data.

I stedet for at bruge en specifik URL til at slette en metode (f.eks. /user/123/delete), sender du en DELETE-forespørgsel til URL'en /user/[id], for at redigere en bruger, og for at hente oplysninger om en bruger sender du en GET-forespørgsel til /user/[id].

I stedet for et sæt URL'er, som f.eks. kan se ud som nogle af følgende...

GET /delete_user.x?id=123
GET /user/delete
GET /new_user.x
GET /user/new
GET /user?id=1
GET /user/id/1

Du bruger HTTP "verber" og har...

GET /user/2
DELETE /user/2
PUT /user
Kommentarer (5)

Det er programmering, hvor arkitekturen i dit system passer til REST-stilen, som Roy Fielding har beskrevet i sin afhandling. Da det er den arkitektoniske stil, der beskriver internettet (mere eller mindre), er der mange mennesker, der er interesserede i den.

Bonus svar: Medmindre du studerer softwarearkitektur som akademiker eller designer webtjenester, er der ingen grund til at have hørt udtrykket.

Kommentarer (4)