[api] RESTful 방식으로 자원에 대한 서버 측 메소드 호출

REST에 대한 기본적인 이해가 있습니다. 이 URL이 있다고 가정 해 봅시다.

http://api.animals.com/v1/dogs/1/

그리고 지금, 서버가 개 껍질을 만들게하고 싶습니다. 서버 만이이를 수행하는 방법을 알고 있습니다. 개가 나머지 영원 동안 10 분마다 짖는 CRON 작업을한다고 가정 해 봅시다. 그 전화는 어떤 모습입니까? 나는 이것을하고 싶다 :

URL 요청 :

ACTION http://api.animals.com/v1/dogs/1/

요청 본문에서 :

{"action":"bark"}

나만의 HTTP 메소드를 만들어서 화가 나기 전에 서버 측 메소드를 RESTful 방식으로 호출하는 방법에 대해 더 나은 아이디어를 제공하십시오. 🙂

설명 편집

“bark”방법의 기능에 대한 설명이 더 있습니다. 다음은 다르게 구조화 된 API 호출을 초래할 수있는 몇 가지 옵션입니다.

  1. bark는 dog.email로 이메일을 보내고 아무것도 기록하지 않습니다.
  2. bark는 dog.email로 이메일을 보내고 dog.barkCount는 1 씩 증가합니다.
  3. bark는 껍질이 발생했을 때 bark.timestamp 기록과 함께 새로운 “bark”레코드를 만듭니다. 또한 dog.barkCount를 1 씩 증가시킵니다.
  4. bark는 시스템 명령을 실행하여 Github에서 최신 버전의 Dog 코드를 가져옵니다. 그런 다음 dog.owner에게 문자 메시지를 보내 새 dog 코드가 작성 중임을 알려줍니다.


답변

RESTful 디자인을 목표로하는 이유는 무엇입니까?

RESTful 원칙 은 ( 임의의 사용자웹 사이트를 쉽게 “서핑”할 수 있도록) 웹 사이트를 웹 서비스 API 디자인 에 쉽게 제공하는 기능을 제공하므로 프로그래머가 쉽게 사용할 수 있습니다. REST는 REST이기 때문에 좋지 않습니다. REST는 좋기 때문에 좋습니다. 그리고 그것은 단순 하기 때문에 주로 좋습니다 .

일부 기능이 “기능 부족” 이라고 부르는 일반 HTTP (SOAP 엔벨로프 및 단일 URI 오버로드 된 POST서비스가없는) 의 단순성 은 실제로 가장 큰 장점 입니다. HTTP는 즉시 접근성상태 비 저장 을 요구합니다. HTTP는 오늘날의 대규모 사이트 (및 대규모 서비스)까지 확장 가능한 두 가지 기본 설계 결정입니다.

그러나 REST는 은색이 아닙니다. 때로는 RPC 스타일 ( “원격 프로 시저 호출”(예 : SOAP)) 이 적합 할 수 있으며 때로는 웹의 미덕보다 다른 요구가 우선합니다. 이건 괜찮아. 우리가 정말로 싫어하는 것은 불필요한 복잡성 입니다. 프로그래머 나 회사가 너무 자주 일반 HTTP가 잘 처리 할 수있는 작업을 위해 RPC 스타일 서비스를 도입하는 경우가 너무 많습니다. 그 결과 HTTP가 “실제로”진행중인 것을 설명하는 거대한 XML 페이로드에 대한 전송 프로토콜로 축소됩니다 (URI 또는 ​​HTTP 메소드가 이에 대한 실마리를주지 않음). 결과 서비스는 너무 복잡하고 디버깅이 불가능하며 클라이언트가 개발자가 의도 한대로 정확하게 설정 하지 않으면 작동하지 않습니다 .

Java / C # 코드가 객체 지향적 이지 않은 것과 같은 방식으로 HTTP를 사용하더라도 디자인이 RESTful하지 않습니다. 조치와 호출해야하는 원격 방법의 관점에서 서비스 대한 생각을 서두르고있을 수도 있습니다 . 이것이 주로 RPC 스타일 서비스 (또는 REST-RPC- 하이브리드)로 끝나는 것은 당연합니다. 첫 번째 단계는 다르게 생각하는 것입니다. RESTful 디자인은 여러 가지 방법으로 달성 할 수 있습니다. 한 가지 방법은 작업이 아니라 리소스 측면에서 애플리케이션생각 하는 것입니다.

💡 수행 할 수있는 행동을 생각하는 대신 ( “지도에서 장소 검색”) …

… 이러한 조치 의 결과 ( “검색 기준과 일치하는 장소 목록”)로 생각하십시오.

아래 예를 들어 보겠습니다. (REST의 다른 주요 측면은 HATEOAS를 사용하는 것입니다. 여기서 브러시하지는 않지만 다른 게시물에서 빠르게 이야기합니다 .)

첫 번째 디자인의 문제

제안 된 디자인을 살펴 보자.

ACTION http://api.animals.com/v1/dogs/1/

먼저 새로운 HTTP 동사 ( ACTION)를 만드는 것을 고려해서는 안됩니다 . 일반적으로 몇 가지 이유로 바람직하지 않습니다 .

  • (1) 서비스 URI 만 주어지면 “랜덤”프로그래머는 ACTION동사가 어떻게 존재 하는지 알 수 있습니까?
  • (2) 프로그래머가 존재한다는 것을 알고 있다면, 그 의미를 어떻게 알 수 있습니까? 그 동사는 무엇을 의미합니까?
  • (3) 그 동사가 어떤 속성 (안전성, dem 등식)을 기대해야합니까?
  • (4) 프로그래머에게 표준 HTTP 동사 만 처리하는 매우 간단한 클라이언트가있는 경우 어떻게해야합니까?
  • (5)

이제 사용을 고려해POST 봅시다 (아래에서 왜 그런지 설명하겠습니다. 지금 내 말을 들어보십시오).

POST /v1/dogs/1/ HTTP/1.1
Host: api.animals.com

{"action":"bark"}

확인을 할 수 …하지만 경우에만 :

  • {"action":"bark"}문서였다; 과
  • /v1/dogs/1/“문서 프로세서”(공장과 같은) URI였습니다. “문서 프로세서”는 URI를 단지 “에 던져”하고 “잊어 버린”URI입니다. 프로세서는 “던지기”후에 새로 만든 리소스로 리디렉션 할 수 있습니다. 예를 들어, 메시지 브로커 서비스에 메시지를 게시하기위한 URI. 게시 후 메시지 처리 상태를 표시하는 URI로 리디렉션합니다.

나는 당신의 시스템에 대해 잘 모르지만, 나는 이미 둘 다 사실이 아니라고 확신합니다.

  • {"action":"bark"} 는 문서가 아니며 실제로 서비스 에 닌자 몰래 들어 가려는 방법입니다 . 과
  • /v1/dogs/1/URI는 “개”리소스 (와 아마 개 대표 id==1)이 아닌 문서 프로세서를.

이제 우리가 아는 것은 위의 디자인이 너무 RESTful 한 것이 아니라 정확히 무엇입니까? 뭐가 그렇게 나쁜가요? 기본적으로 복잡한 의미를 가진 복잡한 URI이기 때문에 나쁘다. 아무것도 추론 할 수 없습니다. 프로그래머가 개에게 bark비밀리에 개가 주입 될 수 있는 행동이 있다는 것을 어떻게 알 수 POST있을까요?

질문의 API 호출 디자인

따라서 추격을 줄이고 리소스 측면에서 생각 하여 휴식을 취하도록 디자인하십시오 . Restful Web Services 책 을 인용하겠습니다 .

POST요청은 기존에서 새 자원을 작성하기위한 시도이다. 기존 자원은 데이터 구조적 의미에서 새로운 자원의 부모 일 수 있으며, 트리의 루트는 모든 리프 노드의 부모입니다. 또는 기존 자원은
다른 자원을 생성하는 것이 유일한 목적인 특수 “공장” 자원 일 수 있습니다 . POST요청 과 함께 전송 된 표현 은 새로운 자원의 초기 상태를 설명합니다. PUT과 마찬가지로 POST요청에는 표현이 전혀 포함될 필요가 없습니다.

우리가 볼 수있는 위의 설명을 다음 bark과 같이 모델링 할 수 의 하위 리소스dog (A가 있기 때문에 bark, 껍질은 “짖었다”입니다 개, 내에 포함 하여 개).

그 추론에서 우리는 이미 얻었습니다.

  • 방법은 POST
  • 리소스는 “factory”를 나타내는 /barksdog :의 하위 리소스입니다 . 해당 URI는 개마다 고유합니다 (아래에 있으므로 )./v1/dogs/1/barksbark/v1/dogs/{id}

이제 목록의 각 사례마다 특정 동작이 있습니다.

1. 껍질은 단지 전자 메일을 보내고 dog.email아무것도 기록하지 않습니다.

첫째, 짖는 소리 (이메일 보내기)는 동기식 작업이든 비동기식 작업입니까? 둘째, bark요청에 문서 (이메일 등)가 필요합니까, 아니면 비어 있습니까?

1.1 껍질은 전자 메일을 보내고 dog.email아무것도 기록하지 않습니다 (동기식 작업으로)

이 경우는 간단합니다. barks팩토리 자원에 대한 호출은 즉시 껍질 (이메일 전송)을 생성하고 응답 (확인이 가능하거나 그렇지 않은 경우)이 즉시 제공됩니다.

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(entity-body is empty - or, if you require a **document**, place it here)

200 OK

아무것도 기록 (변경)하므로 200 OK충분합니다. 모든 것이 예상대로 진행되었음을 보여줍니다.

1.2 껍질은 전자 메일을 보내고 dog.email아무것도 기록하지 않습니다 (비동기 작업으로)

이 경우 클라이언트는 bark작업 을 추적 할 방법이 있어야합니다 . bark작업은 다음의 자신의 URI의 자원이어야한다 :

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

{document body, if needed;
NOTE: when possible, the response SHOULD contain a short hypertext note with a hyperlink
to the newly created resource (bark) URI, the same returned in the Location header
(also notice that, for the 202 status code, the Location header meaning is not
standardized, thus the importance of a hipertext/hyperlink response)}

202 Accepted
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

이 방법으로 각각 bark추적 할 수 있습니다. 그러면 클라이언트는 URI에 a GET를 발행하여 bark현재 상태를 알 수 있습니다. 어쩌면 a DELETE를 사용 하여 취소 할 수도 있습니다.

2. 껍질은 이메일을 보낸 dog.email다음 dog.barkCount1 씩 증가 합니다.

클라이언트에게 dog리소스가 변경 되었음을 알리려면 더 까다로울 수 있습니다 .

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

{document body, if needed; when possible, containing a hipertext/hyperlink with the address
in the Location header -- says the standard}

303 See Other
Location: http://api.animals.com/v1/dogs/1

이 경우 location헤더의 의도는 클라이언트에게 살펴보아야한다는 것을 알리는 것 dog입니다. 보내는 사람 에 대한 HTTP RFC303 :

이 방법은 주로 POST활성화 된 스크립트 의 출력이 사용자 에이전트를 선택된 자원으로 경로 재 지정할 수 있도록하기 위해 존재
합니다.

작업이 비동기 인 경우 상황과 bark마찬가지로 하위 리소스가 필요 하며 작업이 완료되면 at을 반환해야합니다 .1.2303GET .../barks/Y

3. 껍질은 껍질이 생겼을 때 bark기록 된 새로운 ” “레코드를 생성합니다 bark.timestamp. 또한 dog.barkCount1 씩 증가 합니다.

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(document body, if needed)

201 Created
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

여기에서는 bark요청으로 인해 생성되었으므로 상태 201 Created가 적용됩니다.

생성이 비동기 인 경우 대신 HTTP RFC에 표시된대로 a 202 Accepted가 필요 합니다.

저장된 타임 스탬프는 bark리소스 의 일부이며 a GET를 사용하여 검색 할 수 있습니다 . 업데이트 된 개는 그 안에 “문서화”될 수 있습니다 GET dogs/X/barks/Y.

4. bark는 시스템 명령을 실행하여 Github에서 최신 버전의 Dog 코드를 가져옵니다. 그런 다음 dog.owner새 개 코드가 생산 중임 을 알리는 문자 메시지를 보냅니다 .

이 표현은 복잡하지만 간단한 비동기 작업입니다.

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(document body, if needed)

202 Accepted
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

그런 다음 클라이언트는 GETs를 발행 /v1/dogs/1/barks/a65h44하여 현재 상태를 알 수 있습니다 (코드를 가져 오면 전자 메일이 소유자에게 전송 된 것 등). 개가 바뀔 때마다 a 303가 적용됩니다.

마무리

인용 로이 필딩 :

REST가 메소드에 요구하는 유일한 것은 모든 자원에 대해 균일하게 정의된다는 것입니다 (즉, 중개자가 요청의 의미를 이해하기 위해 자원 유형을 알 필요가 없음).

위의 예에서 POST균일하게 설계되었습니다. 개를 ” bark“로 만듭니다. 그것은 안전하지 않습니다 (나무 껍질이 자원에 영향을 미침) 또는 i 등성 (각 요청은 새로운 것을 산출합니다 bark)은 POST동사에 잘 맞습니다 .

프로그래머는 알 것하십시오 POSTbarks낳는 bark. 응답 상태 코드 (필요한 경우 엔터티 본문 및 헤더와 함께)는 변경된 내용과 클라이언트가 수행 할 수있는 방법과 진행 방법을 설명하는 작업을 수행합니다.

참고 : 사용 된 주요 소스는 ” 휴식 웹 서비스 “책, HTTP RFCRoy Fielding의 블로그 였습니다.


편집하다:

질문과 답변은 처음 만들어진 이후로 상당히 바뀌 었습니다. 원래의 질문은 URI를 등의 디자인에 대해 질문 :

ACTION http://api.animals.com/v1/dogs/1/?action=bark

아래는 왜 좋은 선택이 아닌지에 대한 설명입니다.

클라이언트가 서버에게 데이터로 무엇을해야하는지 알려주 는 방법메소드 정보 입니다.

  • RESTful 웹 서비스는 메소드 정보를 HTTP 메소드로 전달합니다.
  • 일반적인 RPC 스타일 및 SOAP 서비스는 엔티티 본문 및 HTTP 헤더에 유지됩니다.

어느 부분 의 데이터에 작동 할 수있다 [클라이언트는 서버가 원하는] 범위 지정 정보 .

  • RESTful 서비스는 URI를 사용합니다. SOAP / RPC 스타일 서비스는 다시 한번 엔티티 본문과 HTTP 헤더를 사용합니다.

예를 들어 Google의 URI를 사용하십시오 http://www.google.com/search?q=DOG. 방법 정보가 GET있고 범위 지정 정보는 /search?q=DOG입니다.

간단히 말해 :

  • 에서 편안하고 아키텍처 , 방법 정보는 HTTP 메소드로 들어갑니다.
  • 에서 자원 지향 아키텍처 , 범위 지정 정보는 URI로 들어갑니다.

그리고 경험의 법칙 :

HTTP 메소드가 메소드 정보와 일치하지 않으면 서비스가 RESTful하지 않습니다. 범위 지정 정보가 URI에 없으면 서비스가 자원 지향적이지 않은 것입니다.

당신은 넣을 수 있습니다 “껍질” “행동” 의 URL (또는 엔터티 본문에) 및 사용 POST. 아무런 문제가 없으며 작동하며 가장 간단한 방법 일 수 있지만 RESTful하지는 않습니다 .

서비스를 진정으로 편안하게 유지하려면 한 걸음 물러서서 실제로하고 싶은 일 (자원에 어떤 영향을 미칠지)에 대해 생각해야 할 수도 있습니다.

구체적인 비즈니스 요구에 대해 이야기 할 수는 없지만 예를 들어 보겠습니다. 주문이 URI와 같은 RESTful 주문 서비스를 고려하십시오 example.com/order/123.

이제 주문을 취소하고 싶다고하면 어떻게해야합니까? 그것이 “취소” “행동” 이라고 생각하고 그것을 다음과 같이 설계하려는 유혹을받을 수 있습니다 POST example.com/order/123?do=cancel.

우리가 위에서 이야기했듯이 그것은 RESTful하지 않습니다. 대신, 우리는 수도 PUT의 새로운 표현 orderA의 canceled요소에 전송 true:

PUT /order/123 HTTP/1.1
Content-Type: application/xml

<order id="123">
    <customer id="89987">...</customer>
    <canceled>true</canceled>
    ...
</order>

그리고 그게 다야. 주문을 취소 할 수없는 경우 특정 상태 코드가 반환 될 수 있습니다. ( POST /order/123/canceledEntity-body와 같은 하위 리소스 디자인 true도 간단하게 사용할 수 있습니다.)

특정 시나리오에서 비슷한 것을 시도해 볼 수 있습니다. 개가 짖는 동안 그런 식으로, 예를 들어, GETAT는 /v1/dogs/1/그 정보를 포함 할 수있다 (예를 <barking>true</barking>) . 또는 … 너무 복잡하면 RESTful 요구 사항을 풀고에 충실하십시오 POST.

최신 정보:

답변을 너무 크게 만들고 싶지는 않지만 알고리즘 ( action )을 리소스 집합으로 노출시키는 데 시간이 걸립니다 . 행동 ( “지도에서 장소 검색”) 에 대해 생각하는 대신 , 그 행동의 결과 ( “검색 기준과 일치하는지도에있는 장소 목록 )에 대해 생각해야합니다 .

디자인이 HTTP의 균일 한 인터페이스에 맞지 않는 경우이 단계로 돌아갈 수 있습니다.

쿼리 변수 정보 범위를 지정 하지만 새로운 자원을 나타내지 않습니다 ( /post?lang=en분명히 다른 자원과 동일한 자원 /post?lang=jp임). 오히려 클라이언트 상태 를 전달하는 데 사용됩니다 (예 ?page=10: 상태가 서버에 유지되지 않음 ( ?lang=en여기의 예이기도 함)). 또는 입력 매개 변수알고리즘 자원 ( /search?q=dogs, /dogs?code=1)에 전달합니다. 다시, 별개의 자원이 아닙니다.

HTTP 동사 (방법) 속성 :

?action=somethingURI에 표시 되는 또 다른 분명한 점 은 RESTful이 아니며 HTTP 동사의 속성입니다.

  • GETHEAD안전 (나무 등)이고;
  • PUTi DELETE등원 일 뿐이다.
  • POST 둘 다 아닙니다.

안전 : GET또는 HEAD요청은 서버 상태 변경 요청이 아닌 일부 데이터 읽기 요청입니다. 클라이언트는 10 번 GET또는 HEAD요청을 할 수 있으며 한 번 만들 거나 전혀 만들지 않는 것과 같습니다 .

dem 등원 (Idempotence) : dem 등원 (Idempotent) 연산은 한 번 또는 여러 번 적용해도 동일한 효과를 갖습니다 (수학에서 0을 곱하면 i 등원). DELETE리소스를 한 번 사용하는 경우 다시 삭제하면 동일한 효과가 적용됩니다 (리소스가 GONE이미 존재 함).

POST안전하거나 dem 등하 지 않습니다. POST‘팩토리’리소스에 대해 두 개의 동일한 요청을하면 아마도 동일한 정보를 포함하는 두 개의 하위 리소스가 생길 수 있습니다. 오버로드 된 (URI 또는 ​​entity-body의 메소드) POST모든 베팅이 해제됩니다.

이 두 속성은 모두 신뢰할 수없는 네트워크를 통한 HTTP 프로토콜의 성공에 중요했습니다 GET. 페이지가 완전히로드 될 때까지 기다리지 않고 몇 번 업데이트 했습니까 ()?

조치를 작성 하여 URL에 배치하면 HTTP 메소드 계약이 명확하게 중단됩니다. 다시 한번,이 기술은 당신을 허용하지만, 당신은 그것을 할 수 있지만 RESTful 디자인은 아닙니다.


답변

나는 이전에 대답 하지만,이 답변이 내 옛날 대답 모순과 해결책에와 주셔서 매우 다른 전략을 따른다. REST 및 HTTP를 정의하는 개념에서 HTTP 요청을 작성하는 방법을 보여줍니다. 또는 PATCH대신에 사용 합니다 .POSTPUT

REST 제약 조건, HTTP 구성 요소 및 가능한 솔루션을 거칩니다.

쉬다

REST는 확장 가능하게하기 위해 분산 하이퍼 미디어 시스템에 적용되는 일련의 제약 조건입니다. 액션을 원격으로 제어한다는 맥락에서이를 이해하기 위해서는 상호 연결된 정보를 발견,보고, 수정하기위한 시스템의 일부인 분산 하이퍼 미디어 시스템의 일부로 액션을 원격으로 제어하는 ​​것을 고려해야합니다. 그것이 가치보다 더 문제가된다면, 그것을 RESTful하게 만드는 것은 좋지 않을 것입니다. 포트 80을 통해 서버에서 작업을 트리거 할 수있는 “제어판”유형 GUI를 클라이언트에서 원한다면 HTTP 요청 / 응답 또는 WebSocket을 통한 JSON-RPC와 같은 간단한 RPC 인터페이스를 원할 것입니다.

그러나 REST는 매혹적인 사고 방식이며 문제의 예는 RESTful 인터페이스로 쉽게 모델링 할 수 있으므로 재미와 교육에 대한 도전을 시작합시다.

REST는 4 가지 인터페이스 제약 조건으로 정의 됩니다.

자원의 식별; 표현을 통한 자원의 조작; 자기 설명 메시지; 그리고 응용 프로그램 상태 엔진으로서의 하이퍼 미디어.

한 컴퓨터가 다른 컴퓨터에 개 껍질을 만들도록 지시하는 이러한 제약 조건을 충족하는 인터페이스를 정의하는 방법을 묻습니다. 특히, 인터페이스가 HTTP가되기를 원하며 의도 한대로 사용될 때 HTTP RESTful을 만드는 기능을 버리고 싶지 않습니다.

첫 번째 제약 인 resource identification로 시작하겠습니다 .

이름을 지정할 수있는 모든 정보는 문서 또는 이미지, 임시 서비스 (예 : “로스 앤젤레스의 오늘 날씨”), 기타 리소스 모음, 비가 상 객체 (예 : 사람) 등의 리소스 일 수 있습니다. .

그래서 개는 자원입니다. 식별해야합니다.

보다 정확하게, 자원 R 은 시간적으로 변화하는 멤버쉽 함수 M R ( t )이며, 시간 t에 대해 동등한 엔티티 세트 또는 값에 맵핑된다. 세트의 값은 자원 표현 및 / 또는 자원 식별자 일 수있다 .

당신 은 일련의 식별자와 표현을 취하고 그들이 주어진 시간에 서로 연관되어 있다고 말함으로써 개를 모델링 합니다. 지금은 식별자 “dog # 1″을 사용하겠습니다. 그것은 우리에게 두 번째와 세 번째 제약 : 자원 표현자기-설명을 가져옵니다 .

REST 구성 요소는 표시를 사용하여 해당 자원의 현재 또는 의도 된 상태를 캡처하고 해당 표시를 구성 요소간에 전송함으로써 자원에 대한 조치를 수행합니다. 표현은 일련의 바이트와 그 바이트를 설명하는 표현 메타 데이터입니다.

다음은 개의 의도 된 상태를 캡처하는 일련의 바이트입니다. 즉, 식별자 “개 # 1″과 연관시키려는 표현입니다 (개의 이름, 건강을 고려하지 않으므로 상태의 일부만 나타냄에 유의하십시오) , 또는 심지어 과거 수피) :

이 상태 변경이 적용된 이후 10 분마다 짖고 있으며 무기한 계속 될 것입니다.

이를 설명하는 메타 데이터에 첨부되어야합니다. 이 메타 데이터는 유용 할 수 있습니다.

영어 문장입니다. 의도 된 상태의 일부를 설명합니다. 여러 번받는 경우 첫 번째 효과 만 적용하십시오.

마지막으로 네 번째 제약 조건 인 HATEOAS를 살펴 보겠습니다 .

REST … 애플리케이션을 사용자가 원하는 작업을 수행 할 수있는 정보 및 제어 대안의 응집 구조로 간주합니다. 예를 들어, 온라인 사전에서 단어를 찾아 보는 것은 가상 박물관을 둘러 보거나 시험 공부를 위해 수업 노트 세트를 검토하는 것과 같은 하나의 응용 프로그램입니다. … 응용 프로그램의 다음 제어 상태는 첫 번째 요청 된 자원의 표시에 있으므로 첫 번째 표시를 얻는 것이 우선 순위입니다. … 따라서 모델 응용 프로그램은 현재 표현 세트의 대체 상태 전환 중에서 검토하고 선택하여 한 상태에서 다음 상태로 이동하는 엔진입니다.

RESTful 인터페이스에서 클라이언트는 표시를 받거나 보내야하는 방법을 파악하기 위해 자원 표시를받습니다. 클라이언트가 해당 정보에 도달하기 위해 일련의 표현을 따르는 경우에도 클라이언트가 수신 또는 전송할 수있는 모든 표현을 수신 또는 전송하는 방법을 파악할 수있는 응용 프로그램 어딘가에 표현이 있어야합니다. 이것은 충분히 간단 해 보입니다.

클라이언트는 홈페이지로 식별 된 자원의 표현을 요구합니다. 이에 대한 응답으로 클라이언트가 원하는 모든 개에 대한 식별자를 포함하는 표현을 얻습니다. 클라이언트는 식별자를 추출하여 식별 된 개와 상호 작용할 수있는 방법을 서비스에 요청하며, 서비스는 클라이언트가 개의 의도 된 상태의 일부를 설명하는 영어 문장을 보낼 수 있다고 말합니다. 그런 다음 클라이언트는 그러한 명령문을 전송하고 성공 메시지 또는 오류 메시지를 수신합니다.

HTTP

HTTP는 다음과 같이 REST 제약 조건을 구현합니다.

자원 식별 : URI

자원 표현 : 엔티티 본문

자체 설명 : 메소드 또는 상태 코드, 헤더 및 엔티티 본문의 일부 (예 : XML 스키마의 URI)

증오 : 하이퍼 링크

http://api.animals.com/v1/dogs/1URI 로 결정했습니다 . 클라이언트가 사이트의 일부 페이지에서 이것을 받았다고 가정 해 봅시다.

이 엔티티 본문을 사용합시다 (값은 next타임 스탬프입니다. 값은 0‘요청이 수신 될 때’ 를 의미 함).

{"barks": {"next": 0, "frequency": 10}}

이제 방법이 필요합니다. PATCH 는 우리가 결정한 “의도 된 상태의 일부”설명에 적합합니다.

PATCH 메소드는 요청 엔티티에 설명 된 변경 사항 세트가 Request-URI에 의해 식별 된 자원에 적용되도록 요청합니다.

그리고 일부 헤더 :

엔티티 본문의 언어를 표시하려면 다음을 수행하십시오. Content-Type: application/json

한 번만 발생하는지 확인하려면 다음을 수행하십시오. If-Unmodified-Since: <date/time this was first sent>

그리고 요청이 있습니다.

PATCH /v1/dogs/1/ HTTP/1.1
Host: api.animals.com
Content-Type: application/json
If-Unmodified-Since: <date/time this was first sent>
[other headers]

{"barks": {"next": 0, "frequency": 10}}

성공하면 클라이언트는 204응답 으로 상태 코드를 받거나 새 짖는 일정을 반영하도록 205표시 /v1/dogs/1/가 변경된 경우 클라이언트를 받아야합니다 .

실패하면, 403그리고 유용한 메시지를 받아야합니다 .

서비스가에 대한 응답으로 표현에 스케줄을 반영하는 것은 필수는 아니지만 GET /v1/dogs/1/JSON 표현에 다음이 포함되어 있으면 가장 적합합니다.

"barks": {
    "previous": [x_1, x_2, ..., x_n],
    "next": x_n,
    "frequency": 10
}

cron 작업을 서버가 인터페이스에서 숨기는 구현 세부 사항으로 취급하십시오. 이것이 일반적인 인터페이스의 아름다움입니다. 클라이언트는 서버가 무대 뒤에서 무엇을하는지 알 필요가 없습니다. 필요한 것은 서비스가 요청 된 상태 변경을 이해하고 이에 응답한다는 것입니다.


답변

대부분의 사람들 은이 목적으로 POST 를 사용 합니다 . “다른 HTTP 방법이 적절하지 않은 경우 안전하지 않거나 비등 전적인 작업”을 수행하는 데 적합합니다.

XMLRPC 와 같은 API 는 POST 를 사용 하여 임의 코드를 실행할 수있는 작업을 트리거합니다. “작업”은 POST 데이터에 포함됩니다.

POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181

<?xml version="1.0"?>
<methodCall>
   <methodName>examples.getStateName</methodName>
   <params>
      <param>
         <value><i4>41</i4></value>
         </param>
      </params>
   </methodCall>

RPC는 POST가 서버 측 메소드에 대한 일반적인 HTTP 동사 선택임을 보여주기위한 예입니다. 로이 필딩 (Roy Fielding)POST에 대한 생각은 다음과 같습니다. 그는 지정된 HTTP 메소드를 사용하는 것이 충분하다고 말합니다.

RPC 자체는 리소스 지향적이 아니기 때문에 RESTful하지 않습니다. 그러나 상태 비 저장, 캐싱 또는 계층화가 필요한 경우 적절한 변환을 수행하기가 어렵지 않습니다. 예를 보려면 http://blog.perfectapi.com/2012/opinionated-rpc-apis-vs-restful-apis/ 를 참조하십시오 .


답변

POST는 IS HTTP 방식은 설계 에 대한

데이터 처리 프로세스에 데이터 블록 제공

CRUD로 매핑되지 않은 작업을 처리하는 서버 측 메서드는 Roy Fielding 이 REST에서 의도 한 것이므로 여기에 적합하므로 POST비등 전성으로 만들었습니다. POST정보를 처리하기 위해 대부분의 데이터를 서버 측 메서드에 게시하는 작업을 처리합니다.

즉, 개 짖는 시나리오에서 10 분마다 서버 쪽 껍질을 수행하고 싶지만 어떤 이유로 든 클라이언트에서 발생하는 트리거가 필요하다면, PUTdem 등성 때문에 목적을 더 잘 제공 할 것입니다. 글쎄,이 시나리오에서는 엄격하게 여러 POST 요청이 개를 야옹이하게 할 위험이 없지만 어쨌든 두 가지 유사한 방법의 목적입니다. 비슷한 SO 질문에 대한 나의 대답 은 당신에게 유용 할 수 있습니다.


답변

Barking이 소비자가 행동 할 수있는 내부 / 의존 / 서브 리소스라고 가정하면 다음과 같이 말할 수 있습니다.

POST http://api.animals.com/v1/dogs/1/bark

개 번호 1 껍질

GET http://api.animals.com/v1/dogs/1/bark

마지막 껍질 타임 스탬프를 반환합니다

DELETE http://api.animals.com/v1/dogs/1/bark

적용되지 않습니다! 무시하십시오.


답변

일부 답변의 이전 버전에서는 RPC를 사용하는 것이 좋습니다. 당신은으로 RPC를 볼 필요가없는 것입니다 당신이 REST 제약 조건을 준수하면서 원하는 것을 할 수 있도록 완벽하게 가능.

먼저 액션 매개 변수를 URL에 넣지 마십시오. 의 URL을 정의하는 것을 당신이 조치를 적용하고, 쿼리 매개 변수는 URL의 일부입니다. 전적으로 명사 로 생각해야합니다 . http://api.animals.com/v1/dogs/1/?action=bark다른 명사 인 다른 리소스 http://api.animals.com/v1/dogs/1/입니다. [nb Asker가 ?action=bark질문 에서 URI를 제거했습니다 .] 예를 들어와 비교 http://api.animals.com/v1/dogs/?id=1하십시오 http://api.animals.com/v1/dogs/?id=2. 쿼리 문자열로만 구분되는 다른 리소스 따라서 요청이 본문이없는 기존 메소드 유형 (TRACE, OPTIONS, HEAD, GET, DELETE 등)에 직접 대응하지 않는 한 요청의 조치는 요청 본문에 정의되어야합니다.

다음으로 조치가 “등 전성 “인지 판별하십시오 . 이는 부작용없이 반복 될 수 있음을 의미합니다 (자세한 내용은 다음 단락 참조). 예를 들어, 클라이언트가 원하는 효과가 발생했는지 확실하지 않은 경우 값을 true로 설정하면 반복 될 수 있습니다. 요청을 다시 보내고 값은 그대로 유지됩니다. 숫자에 1을 더하는 것은 dem 등성이 아닙니다. 클라이언트가 Add1 명령을 보내도 제대로 작동하지 않는지 확인하고 다시 보내면 서버가 한두 가지를 추가 했습니까? 당신이 결정하면, 당신이 선택할 수있는 더 나은 위치에있어 PUT그리고 POST당신의 방법에 대해.

dem 등원은 결과를 변경하지 않고 요청을 반복 할 수 있음을 의미합니다 . 이러한 영향에는 로깅 및 기타 서버 관리 활동이 포함되지 않습니다. 첫 번째 예제와 두 번째 예제를 사용하여 두 사람의 이메일을 같은 사람에게 보내는 것은 하나의 이메일을 보내는 것과는 다른 상태가됩니다 (수신인은받은 편지함에 두 개가 있으며 스팸으로 간주 할 수 있음). . 예제 2의 barkCount가 API 사용자가 보거나 클라이언트가 볼 수있는 것에 영향을 미치려는 경우 요청을 비등 전성으로 만드는 것이기도합니다. 사용자 만 볼 수있는 경우 서버 로깅으로 계산되며 and 등원을 결정할 때 무시해야합니다.

마지막으로 수행하려는 작업이 즉시 성공할 수 있는지 여부를 결정하십시오. BarkDog는 빠르게 완료되는 작업입니다. RunMarathon은 아닙니다. 조치가 느린 경우 202 Accepted사용자가 폴링하여 조치가 완료되었는지 확인하기 위해 응답 본문에 URL과 함께를 리턴하는 것을 고려 하십시오. 또는 사용자가 목록 URL에 POST를 /marathons-in-progress/수행 한 다음 조치가 완료되면 진행중인 ID URL에서 URL로 경로 재 지정하십시오 /marathons-complete/.
특정 사례 # 1 및 # 2의 경우 서버가 대기열을 만들고 클라이언트가 주소 배치를 게시합니다. 조치는 SendEmails가 아니라 AddToDispatchQueue와 같은 것입니다. 그런 다음 서버는 대기열을 폴링하여 대기중인 이메일 주소가 있는지 확인하고 발견되면 이메일을 보낼 수 있습니다. 그런 다음 대기중인 조치가 수행되었음을 표시하기 위해 큐를 업데이트합니다. 클라이언트에게 큐의 현재 상태를 표시하는 다른 URI가 있습니다. 전자 메일의 이중 전송을 피하기 위해 서버는 전자 메일을 보낸 사람의 로그를 보관하고 동일한 목록을 두 번 POST하더라도 동일한 주소로 2를 보내지 않도록 각 주소를 확인합니다. 큐

어떤 용도로든 URI를 선택할 때는 조치가 아닌 결과로 생각하십시오. 예를 들어 단어 “dogs”에 대한 검색 결과google.com/search?q=dogs표시 됩니다. 검색을 반드시 수행 할 필요는 없습니다.

목록의 사례 # 3과 # 4도 dem 등원이 아닙니다. 제안 된 다른 효과가 API 디자인에 영향을 줄 수 있다고 제안합니다. 네 가지 경우 모두 “세계 상태”가 변경되므로 동일한 API를 사용합니다.


답변

새로운 답변을보십시오 -이것은 이것과 모순되며 REST와 HTTP를보다 명확하고 정확하게 설명합니다.

여기의 추천 편안하고 될 일이하지만 당연히 유일한 옵션이 아닙니다. 서비스가 요청을받을 때 짖는 소리를 시작하려면 :

POST /v1/dogs/1/bark-schedule HTTP/1.1
...
{"token": 12345, "next": 0, "frequency": 10}

token 이 요청이 몇 번 전송되는지에 관계없이 중복 된 짖는 소리를 방지하는 임의의 숫자입니다.

next다음 껍질의 시간을 나타냅니다. 값은 0‘ASAP’ 을 의미합니다.

당신이 때마다 GET /v1/dogs/1/bark-schedule, 당신은 다음과 같은 것을 얻습니다. 여기서 t 는 마지막 나무 껍질의 시간이고 ut + 10 분입니다.

{"last": t, "next": u}

같은 URL을 사용하여 강아지의 현재 짖는 상태에 대해 알아내는 데 사용하는 껍질을 요청하는 것이 좋습니다. REST에 반드시 필요한 것은 아니지만 스케줄을 수정하는 작업을 강조합니다.

적절한 상태 코드는 아마도 205 입니다. 현재 일정 POST을보고 동일한 URL을보고 변경하고 서비스에 의해 일정이 변경되었음을 증명하는 두 번째 모양을 제공하도록 지시 하는 클라이언트를 상상하고 있습니다.

설명

쉬다

잠시 HTTP를 잊어 버리십시오. 리소스 는 입력으로 시간이 걸리고 식별자표현이 포함 집합을 반환하는 함수라는 것을 이해해야합니다 . 자원은 식별자와 표현 의 집합 R 이며; R 은 변경 가능-멤버를 추가, 제거 또는 수정할 수 있습니다. (그것의 나쁜 불안정 디자인은 제거하거나 식별자를 수정합니다. 할 수 있지만) 우리의 요소 식별자 말할 R의 식별의 R을 , 그리고 요소 인 표현한다는 R이 나타내는 R을 .

R 이 개 라고 가정 해 봅시다 . R을 로 식별 합니다 /v1/dogs/1. (의미 /v1/dogs/1R 의 멤버입니다 .) 이것은 R을 식별 할 수있는 많은 방법 중 하나 일뿐 입니다. R/v1/dogs/1/x-rays및로 식별 할 수도 있습니다 /v1/rufus.

R을 어떻게 표현 합니까? 아마 사진과 함께. 엑스레이 세트 일 수도 있습니다. 또는 R이 마지막으로 짖은 날짜와 시간을 나타내는 것일 수도 있습니다. 그러나 이것들은 모두 같은 자원의 표현이라는 것을 기억하십시오 . /v1/dogs/1/x-raysR 은 언제 껍질을 벗겼 을까?”라는 질문에 대한 답변으로 표시되는 동일한 자원의 식별자입니다.

HTTP

원하는 리소스를 참조 할 수없는 경우 리소스를 여러 번 나타내는 것은 그리 유용하지 않습니다. 이것이 HTTP가 유용한 이유입니다 : 식별자를 표현에 연결할 수 있습니다 . 즉, 서비스가 URL을 수신하고 클라이언트에 제공 할 표현을 결정하는 방법입니다.

적어도 그게 GET그렇습니다. PUT의 역은 기본적으로 GET: 당신은 PUT표현의 R 의 URL에서 당신은 미래를 위해 원하는 경우 GET반환 할 해당 URL에 대한 요청 R을 HTML로 JSON과 같은 몇 가지 가능한 번역과 함께.

POST표현을 수정하는 느슨한 방법입니다. 동일한 URL에 해당하는 서로 대응되는 표시 논리와 수정 논리가 있다고 생각하십시오. POST 요청은 서비스가 적합하다고 생각되는 정보를 처리하고 동일한 URL로 표시되는 표현뿐만 아니라 모든 표현을 수정하기위한 수정 로직의 요청입니다. 9.6 PUT 이후 세 번째 단락에주의를 기울이십시오 . URL의 내용을 새 컨텐츠로 바꾸지 않습니다. URL에서 정보를 처리하고 정보 표현의 형태로 지능적으로 응답하도록 요청합니다.

우리의 경우, /v1/dogs/1/bark-schedule정보를 처리하고 그에 따라 몇 가지 표현을 수정하기 위해 수정 로직 (디스플레이 로직이 마지막 짖는 시간과 다음 짖는 시간을 알려주는 표시 로직의 대응)을 요청합니다. 미래에 대한 응답으로 GET, 동일한 URL에 해당하는 디스플레이 로직은 개가 원하는대로 짖고 있음을 알려줍니다.

크론 작업을 구현 세부 사항으로 생각하십시오. HTTP는 표현을보고 수정합니다. 이제부터 서비스는 개가 마지막으로 짖은 시간과 다음에 짖는 시간을 고객에게 알려줍니다. 서비스의 관점에서 볼 때 이는 과거와 계획된 크론 작업과 일치하기 때문에 정직합니다.