수색…


비고

이 절에서는 나머지 내용과 개발자가 왜 사용하고 싶어하는지에 대한 개요를 제공합니다.

또한 휴식 시간에 큰 주제를 언급하고 관련 주제에 링크해야합니다. 나머지 문서는 새로운 내용이므로 관련 주제의 초기 버전을 만들어야 할 수도 있습니다.

REST 개요

REST는 RE Presentational S tate T transfer의 약자로 Roy Fielding 이 박사 학위 논문 건축 스타일과 네트워크 기반 소프트웨어 아키텍처 디자인에 기원합니다. 이 프로젝트에서 그는 다음과 같은 특정 아키텍처 원칙을 확인합니다.

  • 주소 지정 가능 자원 : REST의 정보 및 데이터의 핵심 추상화는 자원이며 각 자원은 URI를 통해 주소 지정이 가능해야합니다.

  • 균일하고 제한적인 인터페이스 : 자원을 조작하기 위해 잘 정의 된 작은 세트를 사용합니다.

  • 표현 지향성 : 하나의 URI가 참조하는 리소스는 다른 형식을 가질 수 있으며 플랫폼마다 다른 형식이 필요합니다. 예를 들어 브라우저에는 HTML이 필요하고 JavaScript에는 JSON이 필요하고 Java 애플리케이션에는 XML, JSON, CSV, 텍스트 등이 필요할 수 있습니다. 해당 서비스의 표현을 사용합니다.

  • 상태없는 통신 : 상태 비 저장 응용 프로그램은 확장하기가 쉽습니다.

  • 응용 프로그램 상태의 엔진 인 Hypermedia : 우리의 데이터 형식이 응용 프로그램의 상태 전환을 유도하게하십시오.

이러한 아키텍처 원칙 세트를 REST라고합니다. REST의 개념은 HTTP의 개념에 영향을받습니다. REST에게 우리에게 준 Roy Fielding은 또한 HTTP 사양의 저자 중 한 명입니다.

웹 서비스 및 RESTful 웹 서비스는 프로그래밍 방식의 액세스를 위해 인터넷에 노출되는 서비스입니다. 그들은 우리의 코드에서 호출 할 수있는 온라인 API입니다. "빅"웹 서비스 SOAP과 REST 웹 서비스의 두 가지 유형이 있습니다.

RESTful 웹 서비스 : REST 아키텍처 개념을 적용하여 작성된 웹 서비스를 RESTful Web Services라고하며, 이는 시스템 자원과 HTTP 프로토콜을 통해 다른 클라이언트로 자원 상태를 전송하는 방법에 중점을 둡니다.

이 문서는 RESTful 웹 서비스에만 중점을두고 있으므로 SOAP WS에 대한 자세한 내용은 다루지 않을 것이다.

RESTful 웹 서비스를 디자인 할 때 엄격한 규칙은 없습니다.

  • 프로토콜 표준 없음
  • 통신 채널 표준 없음
  • 서비스 정의 표준 없음

그러나 SOAP에는이 모든 것에 대한 엄격한 규칙이 있습니다. 모든 SOAP 웹 서비스는 모든 SOAP 웹 서비스가 무엇인지 지시하는 SOAP 사양을 따릅니다. 이 사양은위원회에서 개발하고 관리하며 SOAP WS가 단일 규칙을 따르지 않는다면 정의에 따라 SOAP이 아닙니다.

RESTful 웹 서비스의 개념

RESTful API를 디자인 / 개발하는 동안 고려해야 할 몇 가지 지침이 있습니다.

  1. 리소스 기반 위치 / URI
  2. HTTP 메소드의 올바른 사용
  3. HATEOAS (응용 프로그램 상태의 엔진 인 Hypermedia)

RESTful API를 개발하는 동안의 주요 접근법은 API를 "가능한 한 RESTful"상태로 만드는 것이다.

HTTP를 통한 REST

RESTRoy Fielding이 제안한 프로토콜에 좌우되지 않는 아키텍처로, 분산 시스템의 클라이언트를 서버에서 분리하기 위해 웹 브라우저의 입증 된 개념을 일반화하는 자신의 논문 (5 장은 REST의 프레젠테이션)에서 제안되었습니다.

서비스 나 API가 RESTful이 되려면 다음과 같은 주어진 제약 조건을 따라야한다.

  • 클라이언트 서버
  • 무국적자
  • 캐시 가능
  • 계층화 된 시스템
  • 통일 된 인터페이스
    • 자원 식별
    • 자원 표현
    • 자기 설명 적 메시지
    • 하이퍼 미디어

Fielding의 논문에서 언급 된 제약 외에도 블로그 게시물 REST API는 하이퍼 텍스트 기반이어야하며 Fielding 은 HTTP를 통한 서비스 호출만으로 RESTful이되지는 않는다는 것을 분명히했습니다 . 따라서 서비스는 다음과 같이 요약 된 추가 규칙을 존중해야합니다.

  • API는 기본 프로토콜을 준수해야하며 위반하지 않아야합니다. REST는 HTTP를 통해 대부분 사용되지만이 프로토콜에만 국한되지는 않습니다.

  • 리소스에 중점을두고 미디어 유형을 통한 프레젠테이션.

  • 클라이언트는 API에서 사용 가능한 리소스 또는 반환 된 상태 ( "유형화 된"리소스 )에 대한 초기 지식이나 가정을 가져서는 안되지만 발급 된 요청 및 분석 된 응답을 통해 즉시 학습하십시오. 따라서 클라이언트 구현을 중단하지 않고도 서버를 이동하거나 리소스의 이름을 쉽게 바꿀 수 있습니다.

Richardson 성숙 모델

Richardson Maturity Model 은 RESTful 웹 서비스를 얻기 위해 HTTP를 통해 REST 제약 조건을 적용하는 방법이다.

Leonard Richardson은 애플리케이션을 다음과 같은 4 가지 레이어로 나누었습니다.

  • 수준 0 : 전송에 HTTP 사용
  • 수준 1 : URL을 사용하여 리소스 식별
  • 수준 2 : 상호 작용을위한 HTTP 동사 및 상태 사용
  • 수준 3 : HATEOAS 사용

자원 상태에 대한 표현에 초점을 맞추기 때문에 동일한 자원에 대한 여러 표현을 지원하는 것이 좋습니다. 따라서 표현은 자원 상태에 대한 개요를 제시하는 반면 다른 표현식은 동일한 자원의 전체 세부 사항을 리턴합니다.

주어진 Fielding 제약 조건 은 API가 RMM의 3 단계가 구현 된 후에 만 ​​효과적으로 RESTful 이라는 점에 유의하십시오.


HTTP 요청 및 응답

HTTP 요청은 다음과 같습니다.

  • 동사 (일명 방법), 대부분 GET , POST , PUT , DELETE 또는 PATCH 중 하나입니다.
  • URL
  • 헤더 (키 - 값 쌍)
  • 선택적으로 본문 (일명 페이로드, 데이터)

HTTP 응답은 다음과 같습니다.

HTTP 동사 특성 :

  • 본문이있는 동사 : POST , PUT , PATCH
  • 안전해야하는 동사 (즉, 자원을 수정해서는 안 됨) : GET
  • 멱등수 (즉, 여러 번 실행될 때 자원에 다시 영향을주지 않아야 함) 인 동사 : GET (무효화 가능), PUT , DELETE
        body  safe  idempotent
GET      ✗     ✔     ✔
POST     ✔     ✗     ✗
PUT      ✔     ✗     ✔
DELETE   ✗     ✗     ✔
PATCH    ✔     ✗     ✗

따라서 HTTP 동사를 CRUD 함수 와 비교할 수 있습니다.

PUT 요청은 클라이언트에게 업데이트 된 값으로 전체 리소스를 보내도록 요청 합니다. 부분적으로 자원을 갱신하려면 PATCH Verb를 사용할 수 있습니다 ( 자원을 부분 갱신하는 f} 참조).

일반적인 HTTP 응답 상태

성공

리디렉션

  • 304 (NOT MODIFIED) : 클라이언트는 요청 된 자원의 캐시 된 버전을 사용할 수 있습니다

클라이언트 오류

서버 오류

노트

아무것도 잘못된 반응에 시체를 추가하는 것을 멈추게하여 클라이언트에 대한 거부를 명확하게합니다. 예를 들어, 422 (UNPROCESSABLE ENTITY) 는 다소 모호합니다. 응답 본문은 엔티티를 처리 할 수없는 이유를 제공해야합니다.


증오심

각 자원은 연결된 자원에 하이퍼 미디어를 제공해야합니다. 링크는 적어도 다음 으로 구성됩니다.

  • rel (REL의 ATION을 위해, 일명 이름) : 주요 자원 및 링크 된 하나 (들) 사이의 관계를 설명
  • href : 링크 된 리소스를 대상으로하는 URL

추가 속성은 비추천, 내용 협상 등을 돕기 위해 사용될 수 있습니다.

Cormac Mulhall 은 클라이언트가하려고하는 것에 따라 사용할 HTTP 동사를 결정해야한다고 설명 합니다. 확실하지 않은 경우 API 문서를 통해 모든 하이퍼 미디어와 사용할 수있는 상호 작용을 이해하는 데 도움이됩니다.


미디어 유형

미디어 유형은 자기 설명적인 메시지를 갖는 데 도움이됩니다. 그들은 클라이언트와 서버 사이에서 계약의 일부를 수행하여 리소스와 하이퍼 미디어를 교환 할 수 있습니다.

application/jsonapplication/xml 은 꽤 대중적인 미디어 유형이지만, 많은 의미를 포함하지는 않습니다. 문서에서 사용 된 전체 구문을 설명합니다. HATEOAS 요구 사항을 지원하는보다 특수화 된 미디어 유형을 다음과 같이 사용하거나 ( 공급 업체 미디어 유형을 통해 확장해야합니다.)

클라이언트는 그의 요청에 Accept 헤더를 추가하여 이해할 수있는 미디어 유형을 서버에 알려줍니다. 예를 들면 다음과 같습니다.

Accept: application/hal+json

서버가 그러한 표현으로 요청 된 자원을 생성 할 수 없으면 406 (NOT ACCEPTABLE)을 리턴합니다. 그렇지 않으면 표현 된 자원을 보유한 응답의 Content-Type 헤더에 미디어 유형을 추가합니다 (예 :

Content-Type: application/hal+json

상태없는> 상태 저장

왜?

상태 저장 서버는 클라이언트 세션이 서버 인스턴스 로컬 저장소 (거의 항상 웹 서버 세션에 있음)에 저장된다는 것을 의미합니다. 수평 적 으로 확장 하려고 할 때 문제가되기 시작합니다 :로드 밸런서 뒤에 여러 서버 인스턴스를 숨기면 로그인 할 때 인스턴스 # 1 로 클라이언트가 먼저 전달되고 보호 된 리소스를 가져올 때 인스턴스 # 2 로 먼저 전달됩니다 , 클라이언트 세션이 인스턴스 # 1 에 로컬로 저장되었으므로 두 번째 인스턴스는 요청을 익명 세션 으로 처리합니다.

해결책은 세션 복제 및 / 또는 고정 세션 을 구성하는 것과 같이이 문제를 해결하는 방법으로 발견되었지만 REST 아키텍처는 서버 접근 방식을 변경하지 않고 상태 비 저장으로 만드는 방식을 제안합니다. Fielding에 따르면 :

클라이언트에서 서버로의 각 요청은 요청을 이해하는 데 필요한 모든 정보를 포함해야하며 서버의 저장된 컨텍스트를 이용할 수 없습니다. 따라서 세션 상태는 클라이언트에서 전적으로 유지됩니다.

다시 말해 요청은 인스턴스 # 1 또는 인스턴스 # 2로 전달되었는지 여부에 관계없이 정확히 동일한 방식으로 처리해야합니다. 이것이 무국적 응용 프로그램을 쉽게 확장 할 수있는 이유입니다.

방법?

일반적인 접근법은 토큰 기반 인증 , 특히 트렌디 한 JSON 웹 토큰을 사용하는 것 입니다. 특히 직결 된 JWT는 여전히하지만 몇 가지 문제가 있습니다 무효화만기 자동 연장 (즉, 나를 기억 기능).

사이드 노트

쿠키 또는 헤더 (또는 다른 것)를 사용하는 것은 서버가 상태 저장인지 또는 상태 저장인지 여부와 아무런 관련이 없습니다. 여기에는 토큰 (상태 저장 서버, JWT 등의 세션 식별자)을 전송하는 데 사용되는 미디어 만 있습니다.

RESTful API가 브라우저에서만 사용되는 경우 ( HttpOnly and secure ) 쿠키는 브라우저가 발신 요청에 자동으로 첨부하므로 매우 편리 할 수 ​​있습니다. 쿠키를 선택 하는 경우 CSRF를 인식 해야합니다 (클라이언트가 쿠키와 사용자 지정 HTTP 헤더에서 동일한 고유 한 비밀 값을 생성하여 보내는 것이 좋은 방법입니다).


조건부 요청이있는 캐시 가능 API

Last-Modified 헤더 사용

서버는 캐시 가능한 자원을 보유한 응답에 Last-Modified 날짜 헤더 를 제공 할 수 있습니다. 클라이언트는이 날짜를 자원과 함께 저장해야합니다.

이제 클라이언트가 리소스를 읽기 위해 API를 요청할 때마다 요청을받은 Last-Modified 날짜가 포함 If-Modified-Since 헤더 를 요청에 추가 할 수 있습니다. 그런 다음 서버는 요청의 헤더와 자원의 실제 마지막 수정 날짜를 비교해야합니다. 동등한 경우 서버는 빈 본문이있는 304 (NOT MODIFIED) 를 반환합니다. 요청하는 클라이언트는 현재 캐시 된 리소스를 사용해야합니다.

또한 클라이언트가 리소스를 업데이트하기 위해 API를 요청하면 (즉, 안전하지 않은 동사로) If-Unmodified-Since 헤더를 추가 할 수 있습니다. 이는 경쟁 조건 처리에 도움이됩니다. 헤더와 실제 최종 수정 날짜가 다른 경우 서버는 412 (PRECONDITION FAILED)를 반환합니다. 그런 다음 클라이언트는 자원 수정을 다시 시도하기 전에 자원의 새 상태를 읽어야합니다.

ETag 헤더 사용

ETag (엔터티 태그)는 리소스의 특정 상태에 대한 식별자입니다. 강력한 유효성 검증을 위한 자원의 MD5 해시 또는 약한 유효성 검증을 위한 도메인 특정 ID가 될 수 있습니다.

기본적으로 프로세스는 Last-Modified 헤더와 동일합니다. 서버는 캐시 가능한 리소스를 보유한 응답에 ETag 헤더 를 제공하므로 클라이언트는이 식별자를 리소스와 함께 저장해야합니다.

그런 다음 클라이언트는 수신하고 저장 한 최신 ETag가 들어있는 리소스를 읽을 때 If-None-Match 헤더를 제공합니다. 헤더가 실제 자원의 ETag와 일치하면 서버는 이제 304 (NOT MODIFIED)를 리턴 할 수 있습니다.

다시, 클라이언트는 리소스를 수정할 때 If-Match 헤더를 제공 할 수 있으며 제공된 ETag가 실제와 일치하지 않으면 서버에서 412 (PRECONDITION FAILED) 를 반환해야합니다.

추가 메모

ETag> 날짜

클라이언트가 요청에 날짜와 ETag를 모두 제공하면 날짜를 무시해야합니다. RFC 7232 ( 여기여기 )에서

수신자는 If-Modified-Since / If-Unmodified-Since 무시해야한다. 요청에 If-None-Match / If-Match 헤더 필드가 포함되어 있으면 무시해야한다. If-None-Match / If-Match 의 조건은 If-Modified-Since / If-Unmodified-Since 의 조건을보다 정확하게 대체하는 것으로 간주되며 두 개는 이전 매개체와 상호 운용하기 위해 결합됩니다 If-None-Match / If-Match 구현하지 못할 수도 있습니다.

얕은 ETags

마지막으로 수정 된 날짜 가 리소스 서버 측과 함께 유지된다는 것은 분명하지만 ETag에서는 몇 가지 접근법 을 사용할 수 있습니다.

일반적인 접근법은 얕은 ETag를 구현하는 것입니다 : 서버는 조건부 헤더가 주어지지 않은 것처럼 요청을 처리하지만, 결국에는 반환 할 응답의 ETag를 생성하고 (예 : 해시로) 비교합니다 제공된 것과 함께. HTTP 인터셉터 만 필요하기 때문에 구현하기가 상대적으로 쉽습니다 (그리고 서버에 따라 많은 구현이 이미 존재합니다). 즉,이 접근 방식은 대역폭절약있지만 서버 성능 은 유지할 수 없다는 점을 언급 할 필요가 있습니다.

ETag 메커니즘의 보다 깊은 구현 은 잠재적으로 훨씬 더 큰 이점을 제공 할 수 있습니다. 예를 들어 캐시에서 일부 요청을 처리하고 계산을 전혀 수행하지 않아도되지만 구현은 거의 단순하지 않을 수도 있고 얕은 접근 방식과 같이 플러그 할 수도 없습니다 여기에 설명되어 있습니다.


일반적인 함정

URL에 동사를 넣지 않아도되는 이유는 무엇입니까?

HTTP는 RPC가 아닙니다 . HTTP를 RPC와 크게 다른 점 은 요청이 자원으로 전달된다는 것입니다 . 결국 URL은 URL (Uniform Resource Locator)을 나타내며 URL은 URI ( Uniform Resource Idenfitier)입니다. URL은 당신이 처리 할 자원을 대상으로, HTTP 메소드는 당신이 그것으로 수행 할 작업을 나타냅니다. HTTP 메소드는 동사 로도 알려져 있습니다. URL의 동사는 의미가 없습니다. 링크가 리소스를 대상으로하므로 HATEOAS 관계에 동사도 포함해서는 안됩니다.

리소스를 부분적으로 업데이트하는 방법?

PUT 요청은 업데이트 된 값으로 전체 리소스 를 보내도록 클라이언트에 요청하므로 예를 들어 PUT /users/123 을 사용하여 사용자의 이메일을 간단히 업데이트 할 수 없습니다. 제발 윌리엄 듀란 (William Durand)이 설명했습니다 . 바보처럼 패치하지 마십시오. 몇 가지 REST 호환 솔루션을 사용할 수 있습니다.

  • 리소스의 속성을 공개하고 업데이트 된 값을 보내려면 PUT 메서드를 사용합니다. PUT 사양 은 개별적으로 식별 된 리소스를 더 큰 리소스의 일부와 겹치는 상태로 타겟팅하여 부분 콘텐츠 업데이트가 가능함을 나타냅니다 .
PUT https://example.com/api/v1.2/users/123/email
body:
  new.email@example.com
  • 리소스를 수정해야하는 방법을 설명하는 지침 집합을 포함하는 PATCH 요청을 사용합니다 (예 : JSON 패치 ).
PATCH https://example.com/api/v1.2/users/123
body:
  [
    { "op": "replace", "path": "/email", "value": "new.email@example.com" }
  ]
  • Matt Chapman의 의견 에서 제안 된대로 부분적인 자원 표현을 포함하는 PATCH 요청을 사용하십시오.
PATCH https://example.com/api/v1.2/users/123
body:
  {
    "email": "new.email@example.com"
  }

CRUD 작업의 세계에 맞지 않는 행동은 어떻습니까?

실용적인 RESTful API 설계를위한 Best Practices 에서 Vinay Sahni의 말 :

이것은 일들이 퍼지 어질 수있는 곳입니다. 여러 접근법이 있습니다.

  1. 리소스 필드처럼 보이도록 작업을 재구성하십시오. 작업이 매개 변수를 사용하지 않는 경우에 작동합니다. 예를 들어 활성화 동작을 부울 activated 필드에 매핑하고 패치를 통해 리소스로 업데이트 할 수 있습니다.

  2. RESTful 원칙을 가진 하위 리소스처럼 취급하십시오. 예를 들어, GitHub의의 API는 당신이 할 수 요지 스타PUT /gists/:id/star별표 해제DELETE /gists/:id/star .

  3. 때로는 액션을 합리적인 RESTful 구조로 매핑 할 방법이 없다. 예를 들어, 다중 자원 검색은 특정 자원의 엔드 포인트에 적용되는 것이 타당하지 않습니다. 이 경우 /search 은 리소스가 아닐지라도 가장 의미가 있습니다. 괜찮습니다. API 소비자의 관점에서 올바른 것을하고 혼동을 피하기 위해 명확하게 문서화되어 있는지 확인하십시오.


일반적인 관행

  • API가 문서화됩니다. Swagger 또는 Spring REST Docs 와 같이 문서를 만드는 데 도움이되는 도구가 제공됩니다.

  • API는 헤더를 통해 또는 URL을 통해 버전지정 됩니다.

https://example.com/api/v1.2/blogs/123/articles
                        ^^^^
https://example.com/api/v1.2/blogs/123/articles
                             ^^^^^     ^^^^^^^^
https://example.com/api/v1.2/quotation-requests
                             ^^^^^^^^^^^^^^^^^^
  • HATEOAS는 스스로를 목표로 자원에 대한 "자체"링크 를 제공합니다.
{
  ...,
  _links: {
    ...,
    self: { href: "https://example.com/api/v1.2/blogs/123/articles/789" }
    ^^^^
  }
}
  • HATEOAS 릴레이션은 JavaScript 클라이언트가 링크에 액세스 할 때 JavaScript 명명 규칙을 존중하면서 도트 표기법 을 사용할 수 있도록 lowerCamelCase를 사용합니다 (첫 번째 단어를 제외하고 단어는 소문자로 바뀌고 대문자로 시작하고 공백은 생략됩니다).
{
  ...,
  _links: {
    ...,
    firstPage: { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" }
    ^^^^^^^^^
  }
}

RESTful HTTP API를 통한 블로그 관리

다음 예제는 HAL 을 사용하여 HATOAS를 표현하고 다음을 사용합니다.

  • CURIE (압축 URI) : API 문서에 대한 링크를 제공하는 데 사용됩니다.
  • URI 템플릿 : URI가 해결되기 전에 대체되어야하는 매개 변수를 포함하는 URI

블로그 가져 오기 123

의뢰

GET https://example.com/api/v1.2/blogs/123
headers:
  Accept: application/hal+json

응답

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 123,
    "title": "The blog title",
    "description": "The blog description",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123" },
      "doc:articles": { "href": "https://example.com/api/v1.2/blogs/123/articles{?pageIndex,pageSize}", "templated": true }
    }
  }

블로그에 새 기사 만들기 123

의뢰

POST https://example.com/api/v1.2/blogs/123/articles
headers:
  Content-Type: application/json
  Accept: application/hal+json
  X-Access-Token: XYZ
body:
  {
    "title": "The title 2",
    "content": "The content 2"
  }

응답

status: 201 (CREATED)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2",
    "content": "The content 2",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

블로그 123의 기사 789 개 가져 오기

의뢰

GET https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Accept: application/hal+json

응답

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2",
    "content": "The content 2",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

블로그 123 개 기사 중 4 번째 페이지 가져 오기

의뢰

GET https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25
headers:
  Accept: application/hal+json

응답

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "pageIndex": 4,
    "pageSize": 25,
    "totalPages": 26,
    "totalArticles": 648,
    "_link": {
      "firstPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" },
      "previousPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=3&pageSize=25" },
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25" },
      "nextPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=5&pageSize=25" },
      "lastPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=26&pageSize=25" }
    },
    "_embedded": [
      {
        ...
      }, {
        "id": 456,
        "title": "The title 1",
        "content": "The content 1",
        "_links": {
          "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
          "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/456" },
          "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
          "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/456/comments{?pageIndex,pageSize}", "templated": true }
        }
      }, {
        "id": 789,
        "title": "The title 2",
        "content": "The content 2",
        "_links": {
          "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
          "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
          "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
          "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
        }
      }, {
        ...
      }
    ]
  }

블로그 123의 기사 789 업데이트

의뢰

PUT https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Content-Type: application/json
  Accept: application/hal+json
  X-Access-Token: XYZ
body:
  {
    "id": 789,
    "title": "The title 2 updated",
    "content": "The content 2 updated"
  }

응답

status: 200 (OK)
headers:
  Content-Type: application/hal+json
body:
  {
    "id": 789,
    "title": "The title 2 updated",
    "content": "The content 2 updated",
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
      "doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
    }
  }

노트

  • 업데이트 할 리소스를 식별하는 데 사용되는 식별자 는 URL에있는 식별자입니다 . 본문 에있는 식별자 (있는 경우)는 자동으로 무시해야합니다.
  • PUT 요청은 전체 리소스를 업데이트하기 때문에 아무런 content 도 전송되지 않으면 지속 된 리소스에서 제거되어야합니다.

블로그 123의 기사 789 삭제

의뢰

DELETE https://example.com/api/v1.2/blogs/123/articles/789
headers:
  Accept: application/hal+json
  X-Access-Token: XYZ

응답

status: 204 (NO CONTENT)
headers:
  Content-Type: application/hal+json
body:
  {
    "_links": {
      "curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
      "doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" }
    }
  }

REST 위반

<stock>
    <add>
        <item>
            <name>Milk</name>
            <quantity>2</quantity>
        </item>
    </add>
</stock>

이 본체를 /stocks/123 과 같은 자원에 넣으면 REST의 배경에 위배됩니다. 이 본문을 put 필요한 모든 정보가 들어있는 동안 본문을 처리 할 때 어딘가에 add 할 메서드 호출도 함께 제공됩니다. REST 다음에는 item/stocks/123/items/ 게시됩니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow