긴 쿼리 매개 변수 목록을 사용하여 RESTful 쿼리 API 디자인
몇 가지 필터를 기반으로 일련의 객체를 반환하는 RESTful 쿼리 API를 설계해야합니다. 이에 대한 일반적인 HTTP 메소드는 GET입니다. 유일한 문제는 적어도 12 개의 필터를 가질 수 있으며 모든 필터를 쿼리 매개 변수로 전달하면 URL이 상당히 길어질 수 있습니다 (일부 방화벽에 의해 차단 될 수 있음).
매개 변수 수를 줄이는 것은 옵션이 아닙니다.
내가 생각할 수있는 한 가지 대안은 URI에서 POST 메소드를 사용하고 POST 본문의 일부로 필터를 보내는 것입니다. RESTfull (데이터를 쿼리하기 위해 POST 호출하기)과 반대입니다.
더 나은 디자인 제안이 있습니까?
REST API를 사용하면 모든 관점에서 문제가됩니다.
REST API의 두 가지 주요 개념은 엔드 포인트와 자원 (엔티티)입니다. 느슨하게 말하면, 엔드 포인트는 GET을 통해 자원을 리턴하거나 POST 및 PUT 등을 통해 자원을 승인합니다 (또는 위의 조합).
POST를 사용하면 전송하는 데이터가 새 리소스 및 관련 엔드 포인트를 생성하거나 생성하지 않을 수 있으며, 이는 POSTed URL 아래에 "살아"있지 않을 수 있습니다. 다시 말해 POST 할 때 처리 할 데이터를 어딘가에 보냅니다. POST 엔드 포인트는 일반적으로 자원을 찾을 수있는 위치가 아닙니다.
RFC 2616 에서 인용 (관련 부품은 생략하고 관련 부품은 강조 표시) :
9.5 POST
POST 메소드는 오리진 서버가 요청에 포함 된 엔티티를 요청 라인의 Request-URI에 의해 식별 된 자원의 새로운 하위 항목으로 승인하도록 요청하는 데 사용됩니다. POST는 균일 한 방법으로 다음 기능을 처리 할 수 있도록 설계되었습니다.
- ...
- 양식 제출 결과와 같은 데이터 블록을 데이터 처리 프로세스에 제공하는 단계;
- ...
...
POST 메소드에 의해 수행 된 조치 로 인해 URI로 식별 할 수있는 자원이 생성되지 않을 수 있습니다 . 이 경우 응답 에 결과를 설명하는 엔터티가 포함되는지 여부 에 따라 200 (OK) 또는 204 (No Content)가 적절한 응답 상태 입니다.
오리진 서버에서 리소스가 생성 된 경우 응답은 201 (생성)이어야합니다.
우리는 문제 영역이 지시하는 모든 것, 사용자, 메시지, 서적 등 '사물'또는 '데이터'를 나타내는 엔드 포인트 및 리소스에 익숙해졌습니다. 그러나 엔드 포인트는 다른 자원 (예 : 검색 결과)을 노출 할 수도 있습니다.
다음 예제를 고려하십시오.
GET /books?author=AUTHOR
POST /books
PUT /books/ID
DELETE /books/ID
일반적인 REST CRUD입니다. 그러나 우리가 추가하면 어떨까요 :
POST /books/search
{
"keywords": "...",
"yearRange": {"from": 1945, "to": 2003},
"genre": "..."
}
이 엔드 포인트에 대해 신뢰할만한 것은 없습니다. 요청 본문의 형식으로 데이터 (엔티티)를 허용합니다. 이 데이터는 검색 기준 이며 다른 것과 마찬가지로 DTO입니다. 이 엔드 포인트는 요청에 대한 응답으로 자원 (엔티티)을 생성합니다. 검색 결과 . 검색 결과 리소스는 임시 리소스로 리디렉션없이 클라이언트에 즉시 제공되며 다른 정식 URL에 노출되지 않습니다.
엔티티가 서적이 아닌 경우를 제외하고 여전히 REST입니다. 요청 엔티티는 서적 검색 기준이고 응답 엔티티는 서적 검색 결과입니다.
많은 사람들이 너무 길거나 너무 복잡한 쿼리 문자열을 가진 GET (예 : 쿼리 문자열은 중첩 된 데이터를 쉽게 처리하지 못함) 대신 복잡한 본문 / 긴 데이터를 본문에 표시하여 POST로 전송할 수 있다는 관행을 받아 들였습니다. 요청의.
HTTP 스펙에서 POST 스펙을 찾으십시오. 엄청나게 넓습니다. (RES의 허점을 통해 전함을 항해하고 싶다면 POST를 사용하십시오.)
GET은 dem 등원이므로 자동 재시 도와 같은 GET 시맨틱의 이점 중 일부를 잃어 버릴 수 있지만 그와 함께 살 수 있다면 POST로 길거나 복잡한 쿼리를 처리하는 것이 더 쉬울 수 있습니다.
(Lol long digression ... 최근에 HTTP 사양에 따라 GET 에 문서 본문이 포함될 수 있음을 발견했습니다 . HTTP 작성자가 그것에 대해 이야기하고있는 스레드를 검색하고 발견했으며 라우터와 다른 메시지를 구별 할 필요가 없도록 의도적으로 작성되었습니다. 많은 인프라 스트럭처 조각들이 GET의 몸체를 떨어 뜨릴 수 있으므로 POST와 같이 몸체에 표시된 필터를 사용하여 GET을 수행 할 수 있지만 주사위를 굴릴 수 있습니다.)
간단히 말해서 : POST를 작성하지만 X-HTTP-Method-Override 헤더를 사용하여 HTTP 메소드를 대체하십시오 .
실제 요청
POST / 책
엔터티 본문
{ "title": "Ipsum", "year": 2017 }
Headers
X-HTTP-Method-Override: GET
On the server side, check if header X-HTTP-Method-Override exists then take its value as the method to build the route to the final endpoint in the backend. Also, take the entity body as the query string. From a backend point of view, the request became just a simple GET.
This way you keep the design in harmony with REST principles.
Edit: I know this solution was originally intended to solve PATCH verb problem in some browsers and servers but it also work for me with GET verb in the case of a very long URL which is the problem described in the question.
If you are developing in Java and JAX-RS I recommend you use @QueryParam with @GET
I had the same question when I needed to go through a list.
See example:
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
@Path("/poc")
public class UserService {
@GET
@Path("/test/")
@Produces(MediaType.APPLICATION_JSON)
public Response test(@QueryParam("code") final List<Integer> code) {
Integer int0 = codigo.get(0);
Integer int1 = codigo.get(1);
return Response.ok(new JSONObject().put("int01", int0)).build();
}
}
URI Pattern: “poc/test?code=1&code=2&code=3
@QueryParam will convert the query parameter “orderBy=age&orderBy=name” into java.util.List automatically.
'Programing' 카테고리의 다른 글
이벤트 액션 <> vs 이벤트 EventHandler <> (0) | 2020.06.30 |
---|---|
단위 테스트에서 임의의 데이터? (0) | 2020.06.30 |
라이브러리에서 파이썬 예약어 및 내장 목록을 사용할 수 있습니까? (0) | 2020.06.30 |
UISwipeGestureRecognizer의 방향 설정 (0) | 2020.06.30 |
자기 유형 주석에서 이것과 자기의 차이점은 무엇입니까? (0) | 2020.06.30 |