커스텀 HTTP 메소드 구현에 문제가 있습니까?


34

다음 형식의 URL이 있습니다

/ instance / {instanceType} / {instanceId}

표준 HTTP 메소드 (POST, GET, DELETE, PUT)로 호출 할 수 있습니다. 그러나 "임시 저장"또는 "Curate"와 같이 몇 가지 조치가 더 있습니다.

우리는 DRAFT, VALIDATE, CURATE와 같은 커스텀 HTTP 메소드를 사용할 수 있다고 생각했습니다.

표준은

"HTTP / 1.1에 대한 일반적인 방법 세트는 아래에 정의되어 있습니다.이 세트를 확장 할 수 있지만 추가 방법은 별도로 확장 된 클라이언트 및 서버에 대해 동일한 시맨틱을 공유한다고 가정 할 수 없습니다."

또한 WebDav와 같은 도구는 자체 확장 기능을 만듭니다.

사용자 정의 방법으로 누군가가 겪은 문제가 있습니까? 프록시 서버와 방화벽을 생각하고 있지만 다른 관심 분야는 환영합니다. 안전을 유지하고 action = validate | curate | draft와 같은 URL 매개 변수를 가져야합니까?


6
RFC 1925에서 다시 인용 한 것처럼 "프로토콜 디자인에서 추가 할 항목이 없을 때가 아니라 제거 할 항목이 없을 때 완벽에 도달했습니다." -작동한다면 http에 추가 할 이유가 없습니다.

4
HTTP가 아닌 커스텀 프로토콜을 사용하고 있다는 사실을 아는 한 아무 문제가 없습니다.
user16764

10
@ user16764 "HTTP / 1.1에 대한 일반적인 메소드 세트는 아래에 정의되어 있습니다.이 세트를 확장 할 수 있지만 추가 메소드는 별도로 확장 된 클라이언트 및 서버에 대해 동일한 시맨틱을 공유한다고 가정 할 수 없습니다." w3.org/Protocols/rfc2616/rfc2616-sec9.html는 따라서이 허용됩니다, 그것은 여전히 HTTP입니다
후안 멘데스

imho 메소드 정의는 HTTP / 1.1 범위 내에서 사용자 정의 메소드를 사용하는 것이 이미 허용되지만 동일한 의미를 공유 할 수는 없기 때문에 HTTP에서 추가 / 제거 할 것이 없습니다. 그래서 @MichaelT와 Juan Mendes의 포인트 다소
호소 됨

답변:


42

HTTP의 기본 제약 중 하나 인 REST 중앙 디자인 기능은 모든 자원에 보편적으로 적용되는 작고 고정 된 메소드 세트가 제공 하는 균일 한 인터페이스 입니다. 균일 한 인터페이스 제약 조건에는 여러 가지 단점이 있습니다. 나는 Fielding 으로부터 자유로이 인용하고 있습니다.

균일 한 인터페이스 :

  • 더 간단합니다.
  • 제공하는 서비스에서 구현을 분리합니다.
  • HTTP로드 밸런서 (nginx) 및 캐시 (니스)와 같은 계층 구조를 허용합니다.

반면에 균일 한 인터페이스는 다음과 같습니다.

  • 정보는 응용 프로그램의 요구에 맞는 형식이 아닌 표준화 된 형식으로 전송되기 때문에 효율성이 저하됩니다.

이러한 장단점은 "웹의 일반적인 경우를 위해 설계되었습니다"는 웹 아키텍처의 여러 일반적인 문제에 대한 솔루션을 제공하는 대규모 에코 시스템을 구축 할 수있게 해줍니다. 균일 한 인터페이스를 준수하면 시스템이이 생태계의 이점을 누리면서 깨뜨릴 수 있습니다. nginx와 같은로드 밸런서를 사용하고 싶을 수 있지만 이제는 DRAFT와 CURATE를 이해하는로드 밸런서 만 사용할 수 있습니다. Varnish와 같은 HTTP 캐시 계층을 사용할 수 있지만 이제 DRAFT 및 CURATE를 이해하는 HTTP 캐시 계층 만 사용할 수 있습니다. 서버 오류 문제 해결에 도움을 요청하는 사람이있을 수 있지만 CURATE 요청에 대한 의미를 아는 사람은 없습니다. 새 메소드를 이해하고 올바르게 구현하기 위해 선호하는 클라이언트 또는 서버 라이브러리를 변경하기가 어려울 수 있습니다. 등등.

이를 나타내는 올바른 * 방법 은 자원 (또는 관련 자원) 의 상태 변환 입니다. 게시물을 초안 작성하지 않고 draft상태를 변환 true하거나 draft이전 초안 버전에 대한 변경 사항 및 링크가 포함 된 리소스를 만듭니다 . 게시물을 CURATE하지 않고 curated상태를 변환 true하거나 게시물을 큐 레이트 한 curation사용자와 연결 하는 리소스를 만듭니다 .

* REST 아키텍처 원칙과 가장 밀접한 관련이 있음을 정정하십시오.


로드 밸런싱에 대한 의견에 감사드립니다. 사용자 정의 메소드가 허용되는지 여부를 나타내는 자원에 대해 알고 있습니까?
Juan Mendes

2
WEBDAV와 같이 광범위하게 지원되는 확장 (그리고 그다지 많지 않은)의 일부가 아닌 한 사용자 정의 메소드에는 이점이 없으므로 결코 살펴 보지 않았습니다. 이러한 변경 사항을 상태 변환으로 처리하는 것이 좋습니다. 웹은 우리가 이미 가지고있는 방법으로 잘 작동합니다. PATCH와 같은 균일 한 인터페이스의 일부로 이해되지 않는 한 더 추가해야 할 이유가 없습니다.
Rein Henrichs

5
나는 당신이 당신의 HTTP 서비스가 당신을 위해 작동하는 방식을 디자인 할 때의 이점을 봅니다. 그러나 "추가적인 방법은 동일한 의미론을 공유한다고 가정 할 수 없습니다"-충분하지만, 여전히 HTTP / 1.1 범위의 일부이므로 방화벽, 프록시,로드 밸런서 등은 이러한 가능성을 허용해야합니다. 그렇다면 HTTP / 1.1을 올바르게 구현하지 않습니까?
Prof83

아마 당신은 아마 POV에서 옳았지만, 왜 커스텀 동사가 문제가되는지 알 수 없습니다. 모든 툴은 그것들을 POST처럼 취급해야합니다. 즉, "리소스는 아마도 변화 할 것이고 우리가 아는 전부입니다".
maaartinus

7

나는 이것을 POST 요청을 수행하는 하위 리소스로 디자인하고 싶습니다.

에 리소스가 있다고 가정 해 보겠습니다. /instance/type/1해당 리소스를 표현하면 /instance/type/1/draftand 등의 리소스에서 수행 할 수있는 '작업'에 대한 몇 가지 링크가 전달됩니다 /instance/type/1/curate. JSON에서는 다음과 같이 간단 할 수 있습니다.

{
    "some property":"the usual value",
    "state": "we can still inform the client about the current state",
    "draft": "http://server/instance/type/1/draft",
    "curate": "http://server/instance/type/1/curate"
}

이를 통해 클라이언트는 curate멤버가 제공 한 링크에 대한 POST 요청 중에 발생하는 상황에 대해 매우 명확하게 알 수 있습니다 . 여기에 게시 된 리소스에는 상태 전이를 유발할 수있는 이벤트를 자세히 설명하는 인수가 포함될 수 있습니다.

자원에서 가능한 상태 사이를 이동하는 '순진한'접근 방식으로 진행하면 어떤 이벤트로 인해 이러한 전환이 발생했는지 파악할 수 없다는 단점이 있습니다.

상태 전이는 일반적으로 특정 이벤트에 대한 응답으로 발생하며 클라이언트가 무언가가 특정 '상태'에 있다고 결정하게하는 것보다 해당 이벤트를 캡처하고 싶습니다. 또한 유효성 검사를 훨씬 어렵게 만듭니다. 또한, 주 자체의 설명이 없으면 '인수'를 캡처 할 수 없습니다. 그런 다음 일부 코드가 실제 상태 전환없이 코드를 변경하고 유효성 검사가 필요하면 모든 문제가 발생하여 모든 것이 빠르게 엉망이됩니다.


좋은 대답입니다. 상태 전이에 인수를 제공 할 수 있고 서버가이를 캡슐화하고 관리하도록하는 것이 가장 좋은 방법입니다.
Thomas W

현재 (VMware)에있는 회사에서이 작업을 수행합니다. GET on /vms/some-id은 다음과 같은 동작으로 연결되는 링크를 반환 POST /vms/some-id/restart하며이를 사용하여 동작을 활성화 또는 비활성화할지 결정합니다. 나는 HATEOAS 와 사랑 / 증오 관계가 있습니다 :)
Juan Mendes

취해지는 조치가 임의의 쿼리 매개 변수, 자원 경로 세그먼트 또는 본문 특성 대 요청의 동사 인 경우 훨씬 더 의미가 있습니다.
매튜 화이트

동사에 연결할 수 없습니다.
Dave Van den Eynde

6

커스텀 HTTP 메소드가 엔티티 조치를 구현하는 가장 좋은 방법이라고 생각합니다. 엔티티 본문 (POST)에 조치를 추가하는 것이 옳지 않은 것처럼 보이지만 엔티티의 일부가 아닙니다 (결과가 저장 될 수 있음). 또한 사용자 정의 HTTP 메소드를 사용하면 엔티티 본문을 구문 분석하지 않고도 조치를 결정할 수 있습니다.

CRUD와 마찬가지로 항상 구현하고 싶을뿐 아니라 (자격 당) 고유 한 특정 작업 집합이 있습니다. 나는 그것들을 확장하는데 문제가 무엇인지 알지 못한다.

또한 @Rein Henrichs "포스트를 초안 작성하지 않고, 초안 상태를 true로 변환하거나 초안 리소스를 생성합니다." drafts속성은 지속되지 변환을 만들기 위해, 상태를 저장하는데 사용된다. 동작이 반드시 '상태'가되거나 속성에 저장되는 것은 아닙니다. 각 상태 / 변형에 대해 별도의 엔티티를 작성하는 것은 훨씬 더 애매한 것으로 보입니다. enity에 대해 동일한 참조 (URI)를 유지하십시오.


1
이것은 널리 동의하지 않았음에도 불구하고 정당한 이유이며, 그 이유를 뒷받침 할 수 있으며 공감대에 동의하지 않습니다 (특히 유권자의 의견이없는 경우). PHP 예외 처리를 예로 들어 보자. "Best Practice"는 특정 예외 유형을 사용하여 예외의 종류를 제안하고 RuntimeException vs BadMethodCallException과 같은 실제 메시지를 무시하는 것에 집중하는 것 같습니다. 그렇다면 커스텀 메소드를 사용하는 것이 이미 HTTP / 1.1 범위의 일부로 간주된다면 왜 DRAFT를 사용하지 않는가? 그리고로드 밸런서 및 프록시는이 가능성도 실제로 수용해야합니다.
Prof83
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.