REST 이해 : 동사, 오류 코드 및 인증


602

PHP 기반 웹 응용 프로그램, 데이터베이스 및 CMS의 기본 기능을 중심으로 API를 래핑하는 방법을 찾고 있습니다.

나는 둘러보고 몇 가지 "골격"프레임 워크를 발견했다. 내 질문에 대한 답변 외에도 Tonic , 매우 가벼운 REST 프레임 워크가 있습니다.

REST를 단순성에 가장 적합하고이를 기반으로 API 아키텍처를 만들고 싶습니다. 기본 원칙에 대해 잘 알고 있지만 아직 완전히 이해하지 못했습니다. 따라서 많은 질문이 있습니다.

1. 나는 그것을 올바르게 이해하고 있습니까?

리소스 "사용자"가 있다고 가정하십시오. 다음과 같이 여러 URI를 설정할 수 있습니다.

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

이것이 지금까지 RESTful 아키텍처의 올바른 표현입니까?

2. 동사가 더 필요해

이론적으로 작성, 업데이트 및 삭제로 충분할 수 있지만 실제로는 더 많은 동사가 필요합니다. 나는 이것이 업데이트 요청에 포함될 있는 것들이라는 것을 알고 있지만, 특정 반환 코드를 가질 수있는 특정 작업이므로 모든 작업을 하나의 작업으로 처리하고 싶지 않습니다.

사용자 예제에서 염두에 두는 것은 다음과 같습니다.

activate_login
deactivate_login
change_password
add_credit

RESTful URL 아키텍처의 작업과 같은 작업을 어떻게 표현합니까?

내 본능은 같은 URL에 GET 호출을하는 것입니다.

/api/users/1/activate_login 

상태 코드가 다시 나타날 것으로 예상합니다.

그러나 HTTP 동사를 사용한다는 생각에서 벗어납니다. 어떻게 생각해?

3. 오류 메시지 및 코드를 반환하는 방법

REST의 아름다움 중 상당 부분은 표준 HTTP 메소드 사용에서 비롯됩니다. 오류가 발생하면 3xx, 4xx 또는 5xx 오류 상태 코드가있는 헤더를 내 보냅니다. 자세한 오류 설명을 위해 본문을 사용할 수 있습니다 (오른쪽?). 여태까지는 그런대로 잘됐다. 그러나 무엇이 잘못되었는지 (예 : "데이터베이스에 연결하지 못했습니다"또는 "데이터베이스 로그인이 잘못되었습니다") 설명하는보다 자세한 독점 오류 코드 를 전송하는 방법 은 무엇입니까? 메시지와 함께 본문에 넣으면 나중에 구문 분석해야합니다. 이런 종류의 표준 헤더가 있습니까?

4. 인증 방법

  • REST 원칙에 따른 API 키 기반 인증은 어떤 모양입니까?
  • REST 클라이언트를 인증 할 때 세션을 사용하는 것에 대한 강력한 포인트가 있습니까? 단, REST 원칙에 대한 명백한 위반이 아닌가? :) (여기서 반 농담, 세션 기반 인증은 기존 인프라와 잘 작동합니다.)

13
@Daniel, 편집 해 주셔서 감사합니다. "동사 더"는 고의적 인 말장난 이었지만 그대로두고갔습니다. 지금 읽기가 더 쉽습니다. :)
Pekka

1
오류 설명에 대한 BTW. 응답 헤더에 오류 설명을 넣었습니다. '오류 설명'이라는 헤더를 추가하십시오.
Andrii Muzychuk

이것은 응용 프로그램 보안 질문과 비슷합니다. 애플리케이션 보안은 REST가 아닙니다.
나자르 메르 자

@NazarMerza 1., 2. 및 3. 응용 프로그램 보안 질문은 어떻습니까?
페카

답변:


621

이 질문은 며칠 늦게 나타 났지만 통찰력을 추가 할 수 있다고 생각합니다. RESTful 벤처에 도움이 되길 바랍니다.


포인트 1 : 이해하고 있습니까?

당신은 올바르게 이해했습니다. 이것이 RESTful 아키텍처의 올바른 표현입니다. Wikipedia 의 다음 행렬은 명사와 동사를 정의하는 데 매우 도움 이 될 수 있습니다 .


를 다룰 때 Collection URI를 :http://example.com/resources/

  • GET : 컬렉션의 멤버를 나열하고 추가 탐색을 위해 멤버 URI로 완성하십시오. 예를 들어, 판매 할 모든 자동차를 나열하십시오.

  • PUT : "전체 컬렉션을 다른 컬렉션으로 교체"로 정의 된 의미.

  • POST : 컬렉션에서 ID가 자동으로 할당되는 컬렉션에서 새 항목을 만듭니다. 생성 된 ID는 일반적으로이 작업에서 반환 한 데이터의 일부로 포함됩니다.

  • DELETE : "전체 모음 삭제"로 정의 된 의미입니다.


다음과 같은 멤버 URI를 처리 할 때 :http://example.com/resources/7HOU57Y

  • 가져 오기 : 적절한 MIME 형식으로 표현 된 컬렉션의 주소가 지정된 멤버의 표현을 검색합니다.

  • 놓다 : 컬렉션의 주소가 지정된 멤버를 업데이트하거나 지정된 ID로 생성합니다.

  • 게시하다 : 주소가 지정된 멤버를 자체적으로 컬렉션으로 취급하고 새 하위 항목을 만듭니다.

  • 삭제 : 컬렉션의 주소가 지정된 멤버를 삭제합니다.


포인트 2 : 더 많은 동사가 필요합니다

일반적으로 동사가 더 필요하다고 생각되면 실제로 리소스를 다시 식별해야 할 수도 있습니다. REST에서는 항상 리소스 또는 리소스 모음에서 작업하고 있음을 기억하십시오. 리소스로 선택하는 것은 API 정의에서 매우 중요합니다.

로그인 활성화 / 비활성화 : 새 세션을 생성하는 경우 "세션"을 리소스로 고려할 수 있습니다. 새 세션을 만들려면 http://example.com/sessions/본문의 자격 증명과 함께 POST를 사용하십시오. 만료하려면 PUT 또는 DELETE (세션 기록을 유지할지 여부에 따라 다름)를 사용하십시오 http://example.com/sessions/SESSION_ID.

비밀번호 변경 : 이번에는 자원이 "사용자"입니다. http://example.com/users/USER_ID본문에 이전 암호와 새 암호를 넣을 PUT이 필요합니다 . "사용자"리소스를 사용하고 있으며 비밀번호 변경은 단순히 업데이트 요청입니다. 관계형 데이터베이스의 UPDATE 문과 매우 유사합니다.

내 본능은 같은 URL에 GET 호출을하는 것입니다. /api/users/1/activate_login

이는 매우 중요한 REST 원칙 인 HTTP 동사의 올바른 사용법에 위배됩니다. 모든 GET 요청은 부작용을 남기지 않아야합니다.

예를 들어, GET 요청은 데이터베이스에서 세션을 작성하거나 새 세션 ID로 쿠키를 리턴하거나 서버에 잔여 물을 남기지 않아야합니다. GET 동사는 데이터베이스 엔진의 SELECT 문과 같습니다. 정적 웹 페이지를 요청할 때와 마찬가지로 GET 동사를 사용한 요청에 대한 응답은 동일한 매개 변수로 요청 될 때 캐시 할 수 있어야합니다.


포인트 3 : 오류 메시지 및 코드를 반환하는 방법

4xx 또는 5xx HTTP 상태 코드를 오류 범주로 고려하십시오. 본문의 오류를 자세히 설명 할 수 있습니다.

데이터베이스 연결 실패 : / 잘못된 데이터베이스 로그인 : 일반적으로 이러한 유형의 오류에는 500 오류를 사용해야합니다. 서버 측 오류입니다. 클라이언트는 아무 잘못도 없었다. 500 개의 오류는 일반적으로 "재시도 가능"한 것으로 간주됩니다. 즉, 클라이언트는 동일한 정확한 요청을 다시 시도 할 수 있으며 서버의 문제가 해결되면 성공할 것으로 예상합니다. 고객이 우리에게 어떤 맥락을 제공 할 수 있도록 본문에 세부 사항을 명시하십시오.

다른 범주의 오류는 일반적으로 클라이언트가 잘못한 것을 나타내는 4xx 제품군입니다. 특히,이 범주의 오류는 일반적으로 클라이언트에게 요청이 계속 실패 할 것이므로 요청을 재 시도 할 필요가 없음을 나타냅니다. 즉, 클라이언트는이 요청을 재 시도하기 전에 무언가를 변경해야합니다. 예를 들어 "리소스를 찾을 수 없음"(HTTP 404) 또는 "잘못된 요청"(HTTP 400) 오류가이 범주에 속합니다.


포인트 4 : 인증 방법

포인트 1에서 지적했듯이 사용자를 인증하는 대신 세션 생성에 대해 생각할 수 있습니다. 적절한 HTTP 상태 코드 (200 : 액세스 허용 또는 403 : 액세스 거부)와 함께 새 "세션 ID"가 반환됩니다.

그런 다음 RESTful 서버에 "이 세션 ID의 자원을 얻을 수 있습니까?"라고 묻습니다.

인증 된 모드가 없습니다. REST는 상태 비 저장입니다. 세션을 작성하고이 세션 ID를 매개 변수로 사용하여 서버에 자원을 제공하도록 요청한 후 로그 아웃시 세션을 삭제하거나 만료합니다.


6
매우 좋지만 PUT암호 변경에 대한 사용이 올바르지 않을 수 있습니다. PUT전체 리소스가 필요하므로 HTTP (및 HATEOAS REST)를 준수하기 위해 모든 사용자 속성을 보내야합니다. 오히려, 단순히 사용해야하는 암호를 변경 PATCH하거나 POST.
Lawrence Dol

1
"포스트 : 주소가 지정된 멤버를 자체적으로 컬렉션으로 취급하고 새로운 하위 항목을 생성합니다."에 대해 더 확장하면이 게시물이 완벽하다고 생각합니다. 방법. -Google 검색에서 의미하는 바를 찾았습니다. 그렇지 않으면 큰 답변은 예외입니다.
Martin Konecny

6
나는 마지막 문장에 동의하지 않습니다. REST가 상태 비 저장 방법을 설명하고 있습니다. 세션을 생성하기 위해 로그인 한 다음 일부 작업을 수행 한 후 세션을 종료하기 위해 로그 아웃하는 것이 상태 저장 API의 가장 좋은 예입니다.
Brandon

1
"이것은 매우 핵심적인 REST 원칙에 위배됩니다. HTTP 동사의 올바른 사용법. 어떤 GET 요청도 부작용을 남기지 않아야합니다." -리소스의 적중 횟수를 유지하려면 어떻게합니까?
bobbyalex

1
이 기사는 귀하의 질문에 답변해야합니다. saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices
java_geek

79

간단히 말해서, 당신은 이것을 완전히 거꾸로하고 있습니다.

어떤 URL을 사용해야합니까? 시스템에 필요한 리소스와 해당 리소스를 나타내는 방법 및 리소스와 응용 프로그램 상태 간의 상호 작용을 결정한 후에는 URL이 효과적으로 "무료"로 제공됩니다.

Roy Fielding 을 인용하려면

REST API는 리소스를 표현하고 애플리케이션 상태를 구동하는 데 사용되는 미디어 유형을 정의하거나 기존 표준 미디어 유형에 대한 확장 관계 이름 및 / 또는 하이퍼 텍스트 가능 마크 업을 정의하는 데 거의 모든 설명적인 노력을 기울여야합니다. 관심있는 URI에 사용할 메소드를 설명하는 데는 모든 매체 유형 (대부분의 경우 기존 매체 유형에 의해 이미 정의 된)의 처리 규칙 범위 내에서 완전히 정의되어야합니다. [여기서의 실패는 대역 외 정보가 하이퍼 텍스트 대신 상호 작용을 주도하고 있음을 의미합니다.]

사람들은 항상 URI로 시작하여 이것이 해결책이라고 생각하며, 위에서 언급했듯이 REST 아키텍처에서 핵심 개념을 놓치는 경향이 있습니다. "

솔직히 말해서 많은 URI와 GET, PUT 및 POST를보고 REST가 쉽다고 생각합니다. REST는 쉽지 않습니다. RPC over HTTP는 쉽습니다. HTTP 페이로드를 통해 프록시 된 데이터를 앞뒤로 이동하는 것이 쉽습니다. 그러나 REST는 그 이상입니다. REST는 프로토콜에 구애받지 않습니다. HTTP는 매우 인기가 있고 REST 시스템에 적합합니다.

REST는 미디어 유형, 정의 및 애플리케이션이 하이퍼 텍스트 (링크)를 통해 해당 리소스에 사용 가능한 작업을 수행하는 방식에 있습니다.

REST 시스템의 매체 유형에 대한 다른 견해가 있습니다. 일부는 애플리케이션 특정 페이로드를 선호하는 반면, 일부는 기존 미디어 유형을 애플리케이션에 적합한 역할로 향상시키는 것을 좋아합니다. 예를 들어, 한편으로는 마이크로 포맷 및 기타 메커니즘을 통해 XHTML과 같은 것을 표현으로 사용하는 것과는 달리 응용 프로그램에 적합한 특정 XML 스키마가 있습니다.

두 방법 모두 인간 중심 웹과 기계 기반 웹이 겹치는 시나리오에서 XHTML이 잘 작동하는 반면, 이전의보다 구체적인 데이터 유형은 기계 간 상호 작용을보다 잘 촉진한다고 생각합니다. 상용 형식의 향상으로 인해 콘텐츠 협상이 잠재적으로 어려워 질 수 있습니다. "application / xml + yourresource"는 "application / xhtml + xml"보다 미디어 유형으로 훨씬 더 구체적입니다. 후자는 머신 클라이언트가 실제로 관심이 있거나 그렇지 않은 많은 페이로드에 적용될 수 있기 때문입니다. 내성없이 결정하십시오.

그러나 XHTML은 웹 브라우저와 렌더링이 매우 중요한 휴먼 웹에서 매우 잘 작동합니다.

당신은 응용 프로그램이 결정의 종류에 당신을 안내합니다.

REST 시스템 설계 프로세스의 일부는 시스템의 1 차 자원을 파생 자원과 함께 1 차 자원에 대한 조작을 지원하는 데 필요한 지원 자원을 발견하는 것입니다. 일단 자원이 발견되면 다음 자원으로 인해 자원 내에서 하이퍼 텍스트를 통해 자원 흐름을 보여주는 상태 다이어그램뿐만 아니라 해당 자원의 표현이 나타납니다.

하이퍼 텍스트 시스템에서 자원의 각 표현은 실제 자원 표현과 자원에 사용 가능한 상태 전이를 결합합니다. 각 자원을 그래프의 노드로 간주하고 링크는 해당 노드를 다른 상태로 떠나는 선입니다. 이러한 링크는 클라이언트에게 수행 할 수있는 작업뿐만 아니라 수행해야 할 작업을 알려줍니다 (좋은 링크는 URI와 필요한 미디어 유형을 결합하므로).

예를 들어 다음이있을 수 있습니다.

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

문서는 "users"라는 rel 필드와 "application / xml + youruser"의 미디어 유형에 대해 설명합니다.

이러한 링크는 중복 된 것처럼 보일 수 있으며 모두 동일한 URI와 거의 대화하고 있습니다. 그러나 그들은 아닙니다.

이는 "사용자"관계의 경우 해당 링크가 사용자 콜렉션에 대해 이야기하고 있기 때문에 균일 한 인터페이스를 사용하여 콜렉션에 대해 작업 할 수 있습니다 (모두 GET을 검색하고 DELETE를 사용하여 모두 삭제하는 등).

이 URL에 POST하는 경우 "application / xml + usercollection"문서를 전달해야합니다.이 문서에는 아마도 문서 내에 단일 사용자 인스턴스 만 포함되므로 사용자를 추가하거나 추가하지 않을 수 있습니다. 한번. 아마도 문서에서 컬렉션 대신 단일 사용자 유형을 전달할 수 있다고 제안 할 것입니다.

"검색"링크 및 미디어 유형에 정의 된대로 검색을 수행하기 위해 응용 프로그램에 필요한 사항을 확인할 수 있습니다. 검색 미디어 유형에 대한 설명서는 이것이 어떻게 작동하는지, 결과로 무엇을 기대해야하는지 알려줍니다.

그러나 여기서의 테이크 아웃은 URI 자체가 기본적으로 중요하지 않다는 것입니다. 응용 프로그램은 클라이언트가 아닌 URI를 제어합니다. 몇 가지 '진입 점'외에도 클라이언트는 작업을 위해 애플리케이션이 제공 한 URI를 사용해야합니다.

클라이언트는 미디어 유형을 조작하고 해석하는 방법을 알아야하지만 미디어의 위치를 ​​신경 쓸 필요는 없습니다.

이 두 링크는 ​​고객의 관점에서 의미 적으로 동일합니다.

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

리소스에 집중하십시오. 응용 프로그램에서 상태 전환과 가장 잘 달성되는 방법에 중점을 둡니다.


1
이 매우 깊은 답변에 감사드립니다. 몇 가지 사항이 있습니다. "URL 모양"에서 계획하는 것이 다른 방향으로 진행되고 있음을 알고 있으며 리소스 측면에서도 계획하고 있습니다. URL을 가지고 있으면 개념을 더 쉽게 이해할 수 있습니다. 그것은 내 요구 사항은 여기에서 그것을 정의로 100 % 추적의 REST 원칙을 수행하는 시스템으로 충족 될 수 있음을합니다. 각 리소스 유형에 대한 전체 요구 사항 목록을 작성하여 결정할 수있을 것입니다. 건배.
Pekka

30

re 1 : 지금까지는 괜찮습니다. POST에 대한 응답의 일부로 "201 Created"상태 코드와 함께 "Location :"헤더에 새로 생성 된 사용자의 URI를 반환해야합니다.

다시 2: GET을 통한 활성화는 나쁜 생각이며 URI에 동사를 포함시키는 것은 디자인 냄새입니다. GET에 양식을 반환하는 것을 고려할 수 있습니다. 웹앱에서 제출 버튼이있는 HTML 양식입니다. API 사용 사례에서 계정을 활성화하기 위해 URI가 포함 된 표현을 PUT에 반환 할 수 있습니다. 물론 / users에 대한 POST의 응답에이 URI를 포함 할 수도 있습니다. PUT을 사용하면 요청이 dem 등적입니다. 즉, 클라이언트가 성공에 대해 확신이 없으면 안전하게 다시 보낼 수 있습니다. 일반적으로 동사를 어떤 자원으로 바꿀 수 있는지 생각하십시오 ( "동사 명사"의 종류). 특정 행동이 어떤 방법으로 가장 밀접하게 연계되어 있는지 자문 해보십시오. 예 : change_password-> PUT; 비활성화-> 아마도 삭제; add_credit-> 가능하면 POST 또는 PUT.

re 3. 새로운 상태 코드는 너무 일반적이라고 생각하지 않는 한 전 세계적으로 표준화 될 가치가 있다고 생각하지 않는 한 새로운 상태 코드를 발명하지 마십시오. 사용 가능한 가장 적절한 상태 코드를 사용하십시오 (RFC 2616에서 해당 코드를 모두 읽으십시오). 응답 본문에 추가 정보를 포함하십시오. 정말로 새로운 상태 코드를 발명하려는 경우 다시 생각하십시오. 그래도 여전히 믿으면 적어도 올바른 카테고리 (1xx-> 확인, 2xx-> 정보, 3xx-> 리디렉션; 4xx-> 클라이언트 오류, 5xx-> 서버 오류)를 선택하십시오. 새로운 상태 코드를 발명하는 것이 나쁜 생각이라고 언급 했습니까?

4. 가능하면 HTTP에 내장 된 인증 프레임 워크를 사용하십시오. Google이 GData에서 인증을 수행하는 방식을 확인하십시오. 일반적으로 URI에 API 키를 넣지 마십시오. 확장 성을 높이고 캐싱을 지원하기 위해 세션을 피하십시오. 이전에 발생한 문제로 인해 요청에 대한 응답이 다른 경우 일반적으로 특정 서버 프로세스 인스턴스에 연결됩니다. 세션 상태를 클라이언트 상태로 바꾸거나 (예 : 후속 요청의 일부로 만들기) (서버) 리소스 상태로 바꾸어 명시 적으로 만드는 것이 좋습니다 (예 : 고유 한 URI 제공).


URL에 API 키를 넣지 않는 이유에 대해 토론 할 수 있습니까? 프록시 로그에서 볼 수 있기 때문입니까? 키가 일시적인 시간 기반 인 경우 어떻게합니까? HTTPS를 사용하면 어떻게 되나요?
MikeSchinkel

4
정신을 침해하는 것 외에도 (URI는 식별해야 함) 캐싱을 망치는 것이 주된 결과입니다.
Stefan Tilkov

22

1. 리소스 디자인 방법에 대한 올바른 아이디어를 가지고 있습니다 (IMHO). 나는 아무것도 바꾸지 않을 것입니다.

2. 더 많은 동사로 HTTP를 확장하려고 시도하지 말고 제안 된 동사를 기본 HTTP 메소드 및 자원 측면에서 줄일 수있는 것을 고려하십시오. 예를 들어 activate_login동사 대신 다음과 같은 리소스를 설정할 수 있습니다. /api/users/1/login/active이는 간단한 부울입니다. 로그인을 활성화하려면 PUT'true'또는 1 또는 그 밖의 내용이있는 문서 만 있으면됩니다. 비활성화하려면 PUT비어 있거나 0 또는 false 인 문서가 있습니다.

마찬가지로 비밀번호를 변경하거나 설정하려면 PUTs를 수행하십시오 /api/users/1/password.

크레딧과 같은 것을 추가해야 할 때마다의 관점에서 생각하십시오 POST. 예를 들어, 추가 할 크레딧 수를 포함하는 본문 POST과 같은 리소스에 대한 작업을 수행 할 수 /api/users/1/credits있습니다. PUT동일한 자원에가 부가 아닌 값을 덮어 쓰기하는 데 사용할 수 있습니다. POST본문에 음수가있는 A 는 빼는 식입니다.

3. 기본 HTTP 상태 코드를 확장하지 말 것을 강력히 권합니다. 상황과 정확히 일치하는 것을 찾을 수 없으면 가장 가까운 것을 선택하고 오류 본문을 응답 본문에 넣으십시오. 또한 HTTP 헤더는 확장 가능하다는 것을 기억하십시오. 응용 프로그램은 원하는 모든 사용자 정의 헤더를 정의 할 수 있습니다. 예를 들어, 내가 작업 한 응용 프로그램은 404 Not Found여러 상황에서 반환 할 수 있습니다. 이유 때문에 클라이언트가 응답 본문을 구문 분석하는 대신 X-Status-Extended독점 헤더 상태 코드 확장이 포함 된 새로운 헤더를 추가했습니다 . 따라서 다음과 같은 응답이 표시 될 수 있습니다.

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

이렇게하면 웹 브라우저와 같은 HTTP 클라이언트는 여전히 일반 404 코드로 수행 할 작업을 알 수 있으며보다 정교한 HTTP 클라이언트는 X-Status-Extended보다 구체적인 정보를 위해 헤더 를 보도록 선택할 수 있습니다 .

4. 인증을 위해 가능하면 HTTP 인증을 사용하는 것이 좋습니다. 그러나 IMHO가 쿠키 기반 인증을 사용하는 것이 더 쉬운 경우 아무런 문제가 없습니다.


4
"확장 된"리소스를 사용하여 더 큰 리소스의 작은 부분에 작업을 수행하는 것이 좋습니다.
울리십시오

1
쿠키는 HTTP / REST에서 유효하지만 서버는 쿠키를 상태가 아니므로 세션으로 저장해서는 안됩니다. 쿠키는 HMAC와 같은 값을 저장할 수 있지만 다른 곳에서는 조회하지 않고 분해 할 수 있습니다.
브루스 앨더 슨

14

REST 기초

REST에는 균일 한 인터페이스 제한 조건이 있으며, 이는 REST 클라이언트가 실제 REST 서비스의 애플리케이션 특정 세부 사항 대신 표준에 의존해야하므로 REST 클라이언트는 사소한 변경으로 인해 중단되지 않으며 재사용 가능할 것입니다.

따라서 REST 클라이언트와 REST 서비스간에 계약이 있습니다. 기본 프로토콜로 HTTP를 사용하는 경우 다음 표준이 계약의 일부입니다.

  • HTTP 1.1
    • 메소드 정의
    • 상태 코드 정의
    • 캐시 제어 헤더
    • 수락 및 내용 유형 헤더
    • 인증 헤더
  • IRI (utf8 URI )
  • 몸 (하나를 선택하십시오)
  • 하이퍼 링크
    • 그것들을 포함해야 할 것 (하나 선택)
      • 링크 헤더로 보내기
      • html, atom + xml, hal + json, ld + json & hydra 등과 같은 하이퍼 미디어 응답으로 전송
    • 의미론
      • IANA 링크 관계 및 아마도 사용자 정의 링크 관계 사용
      • 응용 프로그램 별 RDF 어휘 사용

REST에는 상태 비 저장 제한 조건이 있으며, 이는 REST 서비스와 클라이언트 간의 통신이 상태 비 저장이어야 함을 선언합니다. 이는 REST 서비스가 클라이언트 상태를 유지할 수 없으므로 서버 측 세션 스토리지를 가질 수 없음을 의미합니다. 모든 단일 요청을 인증해야합니다. 예를 들어 HTTP 기본 인증 (HTTP 표준의 일부)은 모든 요청과 함께 사용자 이름과 비밀번호를 전송하기 때문에 괜찮습니다.

당신에게 질문에 대답하기 위해

  1. 그렇습니다.

    클라이언트는 IRI 구조에 신경 쓰지 않고, 시맨틱에 관심을 갖습니다. 링크 관계 또는 링크 된 데이터 (RDF) 속성이있는 링크를 따르기 때문입니다.

    IRI에서 중요한 것은 단일 IRI가 단일 리소스 만 식별해야한다는 것입니다. 사용자와 같은 단일 리소스가 여러 IRI를 가질 수 있습니다.

    우리가 왜 좋은 IRI를 사용하는지는 매우 간단합니다 /users/123/password. IRI를 이해하기 만하면 서버에서 라우팅 로직을 작성하는 것이 훨씬 쉽습니다.

  2. PUT, PATCH, OPTIONS 등과 같은 동사가 더 많지만 더 필요하지는 않습니다. 새 동사를 추가하는 대신 새 리소스를 추가하는 방법을 배워야합니다.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (상태 비 저장 제한 때문에 로그인은 REST 관점에서 의미가 없습니다.)

  3. 사용자는 왜 문제가 있는지 신경 쓰지 않습니다. 성공 또는 오류가있을 경우에만 알고 싶어 할 수 있습니다. 예를 들어 "죄송하지만 게시물을 저장할 수 없습니다"등의 오류 메시지가 표시 될 수 있습니다.

    HTTP 상태 헤더는 표준 헤더입니다. 다른 모든 것은 내가 생각하는 몸에 있어야합니다. 단일 헤더로는 자세한 다국어 오류 메시지를 설명하기에 충분하지 않습니다.

  4. 상태 비 저장 제약 조건 (캐시 및 계층화 된 시스템 제약 조건과 함께)은 서비스의 확장 성을 보장합니다. 클라이언트에서 동일한 작업을 수행 할 수있을 때 서버에서 수백만 개의 세션을 유지하고 싶지는 않습니다.

    사용자가 기본 클라이언트를 사용하여 액세스 권한을 부여하면 타사 클라이언트는 액세스 토큰을받습니다. 그런 다음 타사 클라이언트는 모든 요청과 함께 액세스 토큰을 보냅니다. 더 복잡한 솔루션이 있습니다. 예를 들어 모든 단일 요청에 서명 할 수 있습니다. 자세한 내용은 OAuth 매뉴얼을 확인하십시오.

관련 문헌


11

당신이 말한 예에서는 다음을 사용합니다.

activate_login

POST /users/1/activation

deactivate_login

DELETE /users/1/activation

change_password

PUT /passwords (이것은 사용자가 인증되었다고 가정합니다)

add_credit

POST /credits (이것은 사용자가 인증되었다고 가정합니다)

오류의 경우 요청을받은 형식으로 본문에 오류를 반환하므로 다음과 같은 경우 수신하십시오.

DELETE /users/1.xml

XML로 응답을 다시 보내면 JSON 등에도 마찬가지입니다.

인증을 위해서는 http 인증을 사용해야합니다.


1
createURI의 일부로 사용하지 않을 것 입니다 (URI는 명사 여야하고 HTTP 메소드는 해당 명사에서 작동하는 동사 여야 함을 기억하십시오). 대신 /users/1/active간단한 부울이 될 수 있는 자원이 있을 수 있습니다. 해당 자원에 1 또는 0을 PUT하여 설정합니다.
friedo

당신 말이 맞아요, 나는 / create를 꺼 냈습니다. 싱글 톤 리소스에 대한 게시물이어야합니다.
jonnii

3
activation의 이름으로 리소스를 명시 적으로 조작 및 관리하지 않는 한 URI에서도 사용하지 않습니다 /users/1/activation. GET은 무엇을합니까? PUT의 기능은 무엇입니까? URI를 확인하고 있다고 생각합니다. 또한 콘텐츠 유형 협상의 경우 URI에서 제외되고 헤더와 같이 삽입되는 것이 가장 좋습니다 Accept.
Cheeso

6
  1. 새 리소스 URI의 모양을 모르는 경우 (새 사용자를 작성하고, 애플리케이션이 새 사용자에게 ID를 지정 함), 리소스를 업데이트하거나 작성하는 방법에 대한 PUT (예 : 표시 방법)을 알고있는 경우 post를 사용하십시오. : PUT /myfiles/thisismynewfile.txt)
  2. 메시지 본문에 오류 설명을 반환
  3. HTTP 인증을 사용할 수 있습니다 (충분한 경우). 웹 서비스는 stateles이어야합니다

5

PUT기존 엔터티를 업데이트하는 데만 사용해야 하는 (첫 번째 단계) 제안 합니다. POST새로운 것을 만드는 데 사용되어야합니다. 즉

/api/users     when called with PUT, creates user record

나에게 옳지 않다. 그러나 첫 번째 섹션 (reb 동사 사용법)의 나머지 부분은 논리적으로 보입니다.


아마 누군가 이것이 이것이 그의 질문에 대한 답변이 아니라고 생각했을 수도 있습니다
lubos hasko

6
새 엔티티를 작성하기 위해 PUT과 POST를 사용하는 것은 호출자가 자원 이름을 제어 할 때 PUT을 사용하는 것이므로 호출자가 새 자원 이름을 제어 할 때 정확한 자원에 PUT을 사용하고 POST를 수행 할 수 있습니다 (예 : 예).
SteveD

5

상세하지만 HTTP 1.1 메소드 스펙에서 복사되었습니다. http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html .

9.3 GET

GET 메소드는 Request-URI에 의해 식별되는 모든 정보 (엔티티 형태)를 검색하는 것을 의미합니다. Request-URI가 데이터 생성 프로세스를 참조하는 경우, 해당 텍스트가 프로세스의 출력이 아닌 한, 프로세스의 소스 텍스트가 아닌 응답의 엔티티로 리턴되는 생성 된 데이터입니다.

요청 메시지에 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match 또는 If-Range 헤더 필드가 포함 된 경우 GET 메소드의 의미는 "조건부 GET"으로 변경됩니다. 조건부 GET 메소드는 조건부 헤더 필드에 설명 된 상황에서만 엔티티를 전송하도록 요청합니다. 조건부 GET 방법은 클라이언트가 이미 보유한 데이터를 여러 번 요청하거나 전송하지 않고도 캐시 된 엔터티를 새로 고치도록하여 불필요한 네트워크 사용을 줄이려고합니다.

요청 메시지에 Range 헤더 필드가 포함 된 경우 GET 메소드의 의미가 "부분 GET"으로 변경됩니다. 14.35 절에서 설명한 것처럼 부분 GET은 엔티티의 일부만 전송하도록 요청합니다. 부분 GET 방법은 클라이언트가 이미 보유한 데이터를 전송하지 않고 부분 검색된 엔티티를 완료 할 수 있도록함으로써 불필요한 네트워크 사용을 줄입니다.

GET 요청에 대한 응답은 섹션 13에 설명 된 HTTP 캐싱 요구 사항을 충족하는 경우에만 캐시 가능합니다.

양식에 사용될 때 보안 고려 사항은 15.1.3 절을 참조하십시오.

9.5 POST

POST 메소드는 오리진 서버가 요청에 포함 된 엔티티를 요청 라인의 Request-URI에 의해 식별 된 자원의 새로운 하위 항목으로 승인하도록 요청하는 데 사용됩니다. POST는 균일 한 방법으로 다음 기능을 처리 할 수 ​​있도록 설계되었습니다.

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

POST 방법으로 수행되는 실제 기능은 서버에 의해 결정되며 일반적으로 Request-URI에 따라 다릅니다. 게시 된 엔티티는 파일이 포함 된 디렉토리에 종속되거나 뉴스 기사가 게시 된 뉴스 그룹에 종속되거나 레코드가 데이터베이스에 종속 된 것과 동일한 방식으로 해당 URI에 종속됩니다.

POST 메소드에 의해 수행 된 조치로 인해 URI로 식별 할 수있는 자원이 생성되지 않을 수 있습니다. 이 경우 응답에 결과를 설명하는 엔터티가 포함되어 있는지 여부에 따라 200 (OK) 또는 204 (No Content)가 적절한 응답 상태입니다.

오리진 서버에서 리소스가 생성 된 경우 응답은 201 (생성)이어야하고 요청 상태를 설명하고 새 리소스와 위치 헤더를 참조하는 엔터티를 포함해야합니다 (섹션 14.30 참조).

응답에 적절한 Cache-Control 또는 Expires 헤더 필드가 포함되어 있지 않으면이 방법에 대한 응답을 캐시 할 수 없습니다. 그러나 303 (기타 참조) 응답을 사용하여 사용자 에이전트가 캐시 가능한 자원을 검색하도록 지시 할 수 있습니다.

POST 요청은 섹션 8.2에 설정된 메시지 전송 요구 사항을 준수해야합니다.

보안 고려 사항에 대해서는 15.1.3 절을 참조하십시오.

9.6 퍼트

PUT 메소드는 동봉 된 엔티티가 제공된 Request-URI 아래에 저장되도록 요청합니다. Request-URI가 이미 존재하는 자원을 참조하는 경우 동봉 된 엔티티는 원래 서버에있는 수정 된 버전으로 간주해야합니다. Request-URI가 기존 자원을 가리 키지 않고 요청 사용자 에이전트가 해당 URI를 새 자원으로 정의 할 수있는 경우, 오리진 서버는 해당 URI로 자원을 작성할 수 있습니다. 새로운 리소스가 생성되면 오리진 서버는 반드시 201 (Created) 응답을 통해 사용자 에이전트에게 알려야합니다. 기존 자원이 수정되면 요청 완료를 표시하기 위해 200 (OK) 또는 204 (No Content) 응답 코드를 보내야합니다. Request-URI로 자원을 작성하거나 수정할 수없는 경우, 문제의 본질을 반영하는 적절한 오류 응답이 제공되어야한다. 엔터티의 수신자는 이해하지 못하거나 구현하지 않은 Content-* (예 : Content-Range) 헤더를 무시해서는 안되며 이러한 경우 501 (구현되지 않음) 응답을 반환해야합니다.

요청이 캐시를 통과하고 Request-URI가 현재 캐시 된 하나 이상의 엔티티를 식별하는 경우 해당 항목은 오래된 것으로 취급해야합니다. 이 방법에 대한 응답은 캐시 할 수 없습니다.

POST와 PUT 요청의 근본적인 차이점은 Request-URI의 다른 의미에 반영됩니다. POST 요청의 URI는 동봉 된 엔터티를 처리 할 리소스를 식별합니다. 이 리소스는 데이터 수락 프로세스, 다른 프로토콜의 게이트웨이 또는 주석을 허용하는 별도의 엔티티 일 수 있습니다. 반대로 PUT 요청의 URI는 요청으로 둘러싸인 엔티티를 식별합니다. 사용자 에이전트는 의도 된 URI를 알고 있으며 서버는 요청을 다른 자원에 적용해서는 안됩니다. 서버가 요청을 다른 URI에 적용하기를 원하는 경우,

반드시 301 (영구적으로 이동) 응답을 보내야합니다. 그런 다음 사용자 에이전트는 요청을 리디렉션할지 여부에 대한 자체 결정을 내릴 수 있습니다.

단일 리소스는 여러 다른 URI로 식별 될 수 있습니다. 예를 들어, 기사에는 "현재 버전"을 식별하기위한 URI가있을 수 있으며, 이는 각 특정 버전을 식별하는 URI와는 별개입니다. 이 경우 일반 URI에 대한 PUT 요청으로 인해 여러 다른 URI가 오리진 서버에 의해 정의 될 수 있습니다.

HTTP / 1.1은 PUT 메소드가 오리진 서버의 상태에 미치는 영향을 정의하지 않습니다.

PUT 요청은 섹션 8.2에 명시된 메시지 전송 요구 사항을 준수해야합니다.

특정 엔터티 헤더에 다르게 지정되지 않는 한 PUT 요청의 엔터티 헤더는 PUT에 의해 생성되거나 수정 된 리소스에 적용되어야합니다.

9.7 삭제

DELETE 메소드는 오리진 서버가 Request-URI로 식별 된 자원을 삭제하도록 요청합니다. 이 방법은 오리진 서버에서 사람의 개입 (또는 다른 수단)에 의해 무시 될 수 있습니다. 오리진 서버에서 리턴 된 상태 코드가 조치가 성공적으로 완료되었음을 표시하더라도 클라이언트는 조작이 수행되었음을 보증 할 수 없습니다. 그러나 서버는 응답이 제공 될 때 리소스를 삭제하거나 액세스 할 수없는 위치로 이동시키지 않는 한 성공을 나타내서는 안됩니다.

응답에 상태를 설명하는 엔터티가 포함 된 경우 성공적인 응답은 200 (OK)이고, 조치가 아직 제정되지 않은 경우 202 (수락 됨), 조치가 제정되었지만 응답이 포함되지 않은 경우 204 (콘텐츠 없음) 여야합니다. 실체.

요청이 캐시를 통과하고 Request-URI가 현재 캐시 된 하나 이상의 엔티티를 식별하는 경우 해당 항목은 오래된 것으로 취급해야합니다. 이 방법에 대한 응답은 캐시 할 수 없습니다.


2

REST 리턴 코드 정보 : HTTP 프로토콜 코드와 REST 결과를 혼합 하는 것은 올바르지 않습니다.

그러나 많은 구현이 혼합되어있는 것을 보았으며 많은 개발자가 저에게 동의하지 않을 수 있습니다.

HTTP 리턴 코드는 HTTP Request자체 와 관련이 있습니다. REST 호출은 하이퍼 텍스트 전송 프로토콜 요청을 사용하여 수행되며 호출 된 REST 메소드 자체보다 낮은 레벨에서 작동합니다. REST는 개념 / 접근 방식이며 결과 는 비즈니스 / 논리적 결과이며 HTTP 결과 코드는 전송 코드입니다 .

예를 들어, / users /를 호출 할 때 "404를 찾을 수 없음"을 반환하면 혼동 될 수 있습니다.

  • URI가 잘못되었습니다 (HTTP)
  • 사용자를 찾을 수 없습니다 (REST)

"403 금지 / 액세스 거부"는 다음을 의미 할 수 있습니다.

  • 특별 허가가 필요합니다. 브라우저는 사용자 / 암호를 요청하여이를 처리 할 수 ​​있습니다. (HTTP)
  • 서버에 잘못된 액세스 권한이 구성되었습니다. (HTTP)
  • 인증이 필요합니다 (REST)

그리고 목록은 '500 서버 오류'(Apache / Nginx HTTP 발생 오류 또는 REST의 비즈니스 제한 오류) 또는 기타 HTTP 오류 등으로 계속 될 수 있습니다.

코드에서 실패 이유, HTTP (전송) 실패 또는 REST (논리) 실패를 이해하기는 어렵습니다.

HTTP 요청이 실제로 성공적으로 수행 된 경우 레코드의 발견 여부에 관계없이 항상 200 코드를 리턴 해야합니다 . URI 자원이 발견 되어 http 서버에서 처리 되었기 때문 입니다. 예, 빈 세트를 반환 할 수 있습니다. http 결과 200으로 빈 웹 페이지를 수신 할 수 있습니까?

이 대신 200 개의 HTTP 코드와 빈 배열 / 객체가있는 JSON을 반환하거나 부울 결과 / 성공 플래그를 사용하여 수행 된 작업 상태를 알릴 수 있습니다.

또한 일부 인터넷 제공 업체는 귀하의 요청을 가로 채서 404 http 코드를 반환 할 수 있습니다. 이것은 데이터를 찾을 수 없다는 것을 의미하지는 않지만 전송 수준에서 문제가 있습니다.

에서 위키 :

2004 년 7 월 영국의 통신 제공 업체 인 BT Group은 Cleanfeed 콘텐츠 차단 시스템을 배포했으며 Internet Watch Foundation에서 불법으로 식별 한 콘텐츠에 대한 요청에 404 오류를 반환합니다. 다른 ISP는 같은 상황에서 HTTP 403 "금지"오류를 반환합니다. 검열을 은폐하기위한 수단으로 가짜 404 오류를 사용하는 관행도 태국과 튀니지에서보고되었습니다. 2011 년 혁명 이전에 검열이 심했던 튀니지에서 사람들은 가짜 404 오류의 본질을 알게되고 "보이지 않는 검열"을 나타내는 "Ammar 404"라는 가상의 캐릭터를 만들었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.