Какво точно представлява RESTful програмирането?

Какво точно представлява RESTful програмирането?

REST е основният архитектурен принцип на уеб. Удивителното в уеб е фактът, че клиентите (браузъри) и сървърите могат да си взаимодействат по сложни начини, без клиентът да знае предварително нищо за сървъра и ресурсите, които той хоства. Основното ограничение е, че сървърът и клиентът трябва да се споразумеят за използваната медия, която в случая на уеб е HTML.

API, който се придържа към принципите на REST, не изисква клиентът да знае нищо за структурата на API. По-скоро сървърът трябва да предостави всякаква информация, от която клиентът се нуждае, за да взаимодейства с услугата. Пример за това е HTML формуляр: Сървърът посочва местоположението на ресурса и необходимите полета. Браузърът не знае предварително къде да подаде информацията и не знае предварително каква информация да подаде. И двете форми на информация се предоставят изцяло от сървъра. (Този принцип се нарича HATEOAS: Hypermedia As The Engine Of Application State.)

И така, как това се отнася за HTTP и как може да се приложи на практика? HTTP е ориентиран към глаголи и ресурси. Двата глагола, които се използват масово, са GET и POST, които мисля, че всеки ще разпознае. Стандартът HTTP обаче дефинира няколко други, като PUT и DELETE. Тези глаголи се прилагат към ресурсите в съответствие с инструкциите, предоставени от сървъра.

Например, нека си представим, че имаме потребителска база данни, която се управлява от уеб услуга. Нашата услуга използва потребителска хипермедия, базирана на JSON, за която задаваме миметипа application/json+userdb (Може да има и application/xml+userdb и application/whatever+userdb - могат да се поддържат много типове медии). И клиентът, и сървърът са програмирани да разбират този формат, но не знаят нищо един за друг. Както посочва Roy Fielding:

Един REST API трябва да изразходва почти цялото си усилие за описание в определяне на медийния(те) тип(и), използван(и) за представяне на ресурси и управление състоянието на приложението, или в дефиниране на разширени имена на връзки и/или хипертекстови маркировки за съществуващите стандартни медийни типове.

Заявка за базовия ресурс / може да върне нещо подобно:

Запитване

GET /
Accept: application/json+userdb

Отговор

200 OK
Content-Type: application/json+userdb

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

От описанието на нашата медия знаем, че можем да намерим информация за свързани ресурси в раздели, наречени "връзки". Това се нарича Хипермедийни контроли. В този случай можем да разберем от такъв раздел, че можем да намерим списък с потребители, като направим друга заявка за /user:

Запитване

GET /user
Accept: application/json+userdb

Отговор

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"
        }
    ]
}

От този отговор можем да разберем много неща. Например, вече знаем, че можем да създадем нов потребител чрез POST към /user:

Запитване

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

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

Отговор

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"
    }
}

Също така знаем, че можем да променяме съществуващите данни:

Запитване

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

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

Отговор

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"
    }
}

Забележете, че използваме различни HTTP глаголи (GET, PUT, POST, DELETE и т.н.), за да манипулираме тези ресурси, и че единственото знание, което предполагаме от страна на клиента, е нашата медийна дефиниция.

Допълнително четене:

(Този отговор е обект на доста критики за това, че не е разбран смисълът му. В по-голямата си част това е справедлива критика. Това, което първоначално описах, отговаряше по-скоро на начина, по който обикновено се прилагаше REST преди няколко години, когато за първи път написах този текст, отколкото на истинското му значение. Преработих отговора, за да представя по-добре истинското значение).

Коментари (39)

REST използва различни HTTP методи (основно GET/PUT/DELETE) за манипулиране на данни.

Вместо да използвате конкретен URL адрес, за да изтриете метод (например /user/123/delete), ще изпратите заявка DELETE към URL адреса /user/[id], за да редактирате потребител, а за да получите информация за потребител, ще изпратите заявка GET към /user/[id].

Например, вместо набор от URL адреси, които могат да изглеждат като някои от следните..

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

Използвате HTTP "глаголите" и имате..

GET /user/2
DELETE /user/2
PUT /user
Коментари (5)

Това е програмиране, при което архитектурата на вашата система отговаря на стила REST, описан от Рой Филдинг в неговата дисертация. Тъй като това е архитектурният стил, който описва мрежата (повече или по-малко), много хора се интересуват от него.

Бонус отговор: Освен ако не изучавате софтуерна архитектура като академик или не проектирате уеб услуги, наистина няма причина да сте чували този термин.

Коментари (4)