나머지 컬렉션에서의 페이징


134

JSON 문서 ( CouchDB 또는 Persevere 생각)에 직접 REST 인터페이스를 노출하는 데 관심이 있습니다. 내가 겪고있는 문제 GET는 컬렉션이 큰 경우 컬렉션 루트 에서 작업 을 처리하는 방법 입니다.

예를 들어 척하는 것처럼 Questions각 행이 문서로 노출되는 StackOverflow의 테이블을 노출하고 있습니다 (필요한 테이블이 아니라 크기가 큰 '문서'집합의 구체적인 예). 컬렉션에서 사용할 수있게 될 것이다 /db/questions일반적인 CRUD API를 사용하여 GET /db/questions/XXX, PUT /db/questions/XXX, POST /db/questions놀이입니다. 전체 컬렉션을 가져 오는 표준 방법은 GET /db/questions각 행을 순식간에 JSON 객체로 덤프하는 경우 다소 규모가 큰 다운로드가 가능하며 서버 측에서 많은 작업이 수행됩니다.

해결책은 물론 페이징입니다. Dojo는 사용자 정의 범위 단위로 헤더를 사용하는 영리한 RFC2616 호환 확장을 통해 JsonRestStore 에서이 문제점을 해결했습니다 . 결과는 요청 된 범위 만 반환합니다. 쿼리 매개 변수에 비해이 방법의 장점은 쿼리 문자열을 쿼리에 남겨 두는 것입니다 (예 : 또는 예를 들어 , 인코딩 된 예 ).Rangeitems206 Partial ContentGET /db/questions/?score>200%3E

이 접근법은 내가 원하는 행동을 완전히 다룹니다. 문제는 RFC 2616 이 206 응답 (강조 광산)에서 다음을 지정한다는 것입니다.

요청 범위 헤더 필드 (반드시 포함했다 섹션 14.35 ) 원하는 범위를 나타내는, 및 IF-Range 헤더 필드 (포함되어있을 수 부 14.27 요구 조건을하기 참조).

이것은 헤더의 표준 사용법과 관련이 있지만 206 응답이 순진한 클라이언트 / 무작위 사람들이 탐색하는 기본값을 원하기 때문에 문제가됩니다.

솔루션을 찾기 위해 RFC를 자세히 살펴 보았지만 솔루션에 만족하지 않아서 SO가 문제를 해결하는 데 관심이 있습니다.

내가 가진 아이디어 :

  • 돌아 200Content-Range헤더! -나는 이것이 틀렸다고 생각하지 않지만 응답이 부분 내용 일뿐이라는 더 명확한 지표를 선호합니다.
  • 반환400 Range Required -필요한 헤더에 대한 특수 400 응답 코드가 없으므로 기본 오류를 직접 읽고 읽어야합니다. 또한 웹 브라우저 (또는 Resty와 같은 다른 클라이언트)를 통한 탐색이 더 어려워집니다.
  • 쿼리 매개 변수를 사용하십시오 -표준 접근 방식이지만 쿼리를 일시적으로 허용하기를 희망하며 쿼리 네임 스페이스가 줄어 듭니다.
  • 그냥 돌아와 206! -대부분의 고객은 놀라지 않을 것이라고 생각하지만 RFC에서 반드시 필히 반대하지는 않습니다.
  • 사양을 확장하십시오! 반환266 Partial Content -206과 똑같이 동작하지만 Range헤더를 포함해서는 안되는 요청에 대한 응답 입니다. 나는 266이 충돌 문제에 부딪치지 않을 정도로 충분히 높으며 나에게 의미가 있지만 이것이 금기 사항인지 아닌지는 확실하지 않습니다.

나는 이것이 상당히 일반적인 문제라고 생각하고 나는 이것이 일종의 사실상의 방식으로 이루어지기를 원하기 때문에 나 또는 다른 사람이 바퀴를 재발 명하지 않습니다.

컬렉션이 클 때 HTTP를 통해 전체 컬렉션을 노출하는 가장 좋은 방법은 무엇입니까?


21
와우, 그것은 전에 진지한 생각을 한 적이있는 질문의 좋은 예입니다.
Heiko Rupp


1
범위 헤더를 사용하는 Dojo의 접근 방식에 따르면 Accept-Ranges는 확장을 허용하지만, 내가 알 수있는 모든 범위에서 EBNF는 범위를 지원하지 않습니다. tools.ietf.org/html/rfc2616#section-14.35.2 . 사양은 tools.ietf.org/html/rfc2616#section-14.35.1Range = "Range" ":" ranges-specifier 의 후자 가 단순히 "bytes-unit"으로 시작해야하는 "bytes-ranges-specifier"로 설명 되는 위치를 나타냅니다 . ".
Brett Zamir 2016 년

2
Content-Range헤더 (다운로드 할 때 등 대용량 파일을 업로드 할 때 요청과 함께 사용하거나 응답 할 수 있습니다) 몸에 적용됩니다. Range헤더는 특정 범위를 요청하기 위해 사용된다. 헤더가 요청에 포함 206되었을 때 응답해야합니다 Range. 그렇지 않은 경우 응답에 여전히 Content-Range헤더 가 포함될 수 있지만 응답 코드는이어야합니다 200. 이 헤더는 실제로 페이징에 이상적입니다.
Stijn de Witt

그러나 RFC 2616 자체는 "HTTP / 1.1 구현은 다른 단위를 사용하여 지정된 범위를 무시할 수 있습니다"라고 말합니다. 페이지 매김에 범위 헤더를 사용하는 것이 좋습니다. coz 상호 운용성을 손상시킬 수 있습니다.
chetan choulwar

답변:


23

내 생각은 HTTP 범위 확장이 사용 사례에 맞게 설계되지 않았으므로 시도하지 않아야한다는 것입니다. 부분적인 응답을 의미 206하고, 206클라이언트가 요청하는 경우에만 보내야합니다.

Atom에서 사용하는 것과 같은 다른 접근 방식을 고려할 수도 있습니다 (설계에 의한 표현이 부분적 일 수 있으며 상태 200및 잠재적으로 페이징 링크 로 리턴 됨 ). RFC 4287RFC 5005를 참조하십시오 .


14
Dojo 사용법은 완전히 사양 내에 있습니다. 서버가 items범위 단위를 이해하지 못하면 전체 응답을 리턴합니다. 나는 Atom에 익숙하지만 Rest paging의 일반적인 해결책은 아닙니다. 이것은 단일 사례에 대한 해결책이 아니며 일반적인 해결책의 더 많은 것입니다. 모든 문서 / 컬렉션이 Atom 모델에 맞지는 않으며 필요한 경우가 아니면 강제로 강제 할 이유가 없습니다.
Karl Guertin

1
@KarlGuertin 동의합니다. 커뮤니티의 많은 사람들이 실제로 수용 Range하고 Content-Range페이징 목적으로 사용 하는 것처럼 보이기 때문에 이것이 허용되는 답변 입니다.
Stijn de Witt

34

나는 당신들 중 일부와 동의하지 않습니다. REST 서비스를 위해이 기능을 몇 주 동안 사용해 왔습니다. 내가 한 일은 정말 간단합니다. 내 솔루션은 REST 사람들이 컬렉션이라고 부르는 것에 대해서만 의미가 있습니다.

클라이언트는 컬렉션의 어느 부분이 필요한지 나타 내기 위해 "범위"헤더를 포함해야하거나 요청 된 컬렉션이 너무 커서 단일 라운드 트립으로 검색 할 수 없을 때 413 요청 된 엔티티가 너무 큼 오류를 처리 할 준비가되어 있어야합니다.

서버는 206 PARTIAL CONTENT 응답을 전송합니다. 전송 된 리소스 부분을 지정하는 Content-Range 헤더와 컬렉션의 현재 버전을 식별하는 ETag 헤더가 있습니다. 나는 보통 페이스 북과 같은 ETag {last_modification_timestamp}-{resource_id}를 사용하며 컬렉션의 ETag는 가장 최근에 수정 된 리소스의 ETag라고 생각합니다.

컬렉션의 특정 부분을 요청하려면 클라이언트는 "Range"헤더를 사용해야하며, 동일한 컬렉션의 다른 부분을 얻기 위해 이전에 수행 된 요청에서 얻은 컬렉션의 ETag로 "If-Match"헤더를 채워야합니다. 따라서 서버는 요청 된 부분을 보내기 전에 컬렉션이 변경되지 않았는지 확인할 수 있습니다. 최신 버전이 존재하면 클라이언트가 콜렉션을 처음부터 검색하도록 초대하기 위해 412 PRECONDITION FAILED 응답이 리턴됩니다. 이는 현재 요청 된 파트 이전 또는 이후에 일부 자원이 추가되거나 제거되었을 수 있기 때문에 필요합니다.

캐시를 최적화하기 위해 Last-Modified / If-Unmodified-Since와 함께 ETag / If-Match를 사용합니다. 브라우저와 프록시는 캐싱 알고리즘을 위해 둘 중 하나 또는 둘 모두에 의존 할 수 있습니다.

검색 / 필터 쿼리를 포함하지 않으면 URL이 깨끗해야한다고 생각합니다. 당신이 그것에 대해 생각하면, 검색은 컬렉션의 부분보기에 지나지 않습니다. cars / search? q = BMW 유형의 URL 대신 더 많은 cars? manufacturer = BMW가 표시됩니다.


416 "요청한 범위가 만족스럽지 않음"또는 "413"요청 엔티티가 너무 큼을 의미 했습니까?

1
@Mohamed 나는 당신 If-Unmodified-Since이 E-Tag 변형 If-Match보다는 오히려 의미 하는 것 같아요 If-Modified-Since. 즉, 사용 사례에 따라이 제약 조건을 제거하는 것도 고려할 수 있습니다. "최신"스타일 컬렉션과 같이 상단에서만 자라는 컬렉션이 있다고 가정 해 봅시다. 요청 사이에 해당 컬렉션이 변경 될 경우 발생할 수있는 최악의 경우는 컬렉션을 통해 페이지를 방문하는 사용자가 항목을 두 번 보는 것입니다. (그 자체가 유용한 정보이기도합니다. 사용자에게 컬렉션이 변경
되었음을

20
413은 "요청 된 엔터티가 너무 큼"이 아니라 "요청 된 엔터티가 너무 큼"입니다. 예를 들어 파일을 업로드 할 때와 같이 요청 크기가 서버가 처리 할 수있는 크기보다 큽니다. 따라서 이것을 사용하는 것이 완전히 적절하지 않은 것 같습니다.
user247702

@Mohamed 나는 그것이 오래된 질문이라는 것을 알고 있지만 컬렉션의 ETag가 가장 최근에 수정 된 리소스의 ETag 인 경우 컬렉션의 한 리소스를 수정할 때 사용해야하는 If-Match 헤더의 값은 무엇입니까? 클라이언트가 리소스의 마지막 상태를 보지 못하더라도 리소스를 수정할 수 있으므로 컬렉션과 함께 반환 된 ETag의 값을 사용하는 것은 잘못되었습니다.
Mickael Marrache

8
에 대한 사용에 동의하지 않습니다 413. 이것은 오류 코드로, 클라이언트가 서버가 크기로 인해 거부 한 것을 전송 하고 있음을 의미합니다 . 다른 방법은 아닙니다! tools.ietf.org/html/rfc7231#section-6.5.11을 참조하십시오 ( 요청 페이로드, 응답 페이로드 아님).
exhuma

7

여전히 응답 코드 Accept-RangesContent-Ranges함께 리턴 할 수 있습니다 200. 이 두 응답 헤더 는 응답 코드가 명시 적으로 제공 하는 것과 동일한 정보 를 유추 할 수 있는 충분한 정보를 206제공합니다.

Range페이지 매김에 사용 200하고 평범 하게 for 를 반환하도록 합니다 GET.

이 100 % 편안하고 느낌 더 어려워을 검색하지 않습니다.

편집 : 나는 이것에 관한 블로그 게시물을 썼습니다 : http://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html


5

응답 페이지가 두 개 이상이고 전체 컬렉션을 한 번에 제공하지 않으려면 여러 선택이 가능합니까?

에 대한 요청에서 URL 목록이 포함 된 JSON 객체 또는 HTML 페이지뿐만 아니라 각 페이지로 이동하는 방법을 지정하는 헤더 와 함께 /db/questions반환 합니다.300 Multiple ChoicesLink

Link: <>; rel="http://paged.collection.example/relation/paged"
Link: <>; rel="http://paged.collection.example/relation/paged"
...

Link각 결과 페이지에 대해 하나의 헤더가 있으며 (빈 문자열은 현재 URL을 의미하고 URL은 각 페이지마다 동일하며 방금 다른 범위로 액세스 됨) 관계는 다음 Link사양에 따라 사용자 지정으로 정의됩니다 . 이 관계는 귀하의 관습 266또는 위반 사항을 설명합니다 206. 이러한 헤더는 모두 컴퓨터에서 읽을 수있는 버전입니다. 모든 예제에는 이해 클라이언트가 필요하기 때문입니다.

( "범위"라우트를 고수하는 경우 2xx설명 된대로 자신의 리턴 코드가 여기에서 가장 좋은 동작이라고 생각합니다. 애플리케이션에 대해이 작업을 수행해야하며 [ "HTTP 상태 코드는 확장 가능합니다. "], 그럴만한 이유가 있습니다.)

300 Multiple Choices또한 사용자 에이전트가 선택할 수있는 방법을 본문에 제공해야합니다. 고객이 이해하고 있다면 Link헤더를 사용해야합니다 . 사용자가 수동으로 탐색하는 경우 URL을 기반으로 특정 페이지 렌더링을 처리 할 수있는 특수한 "페이징 된"루트 리소스에 대한 링크가있는 HTML 페이지일까요? /humanpage/1/db/questions아니면 그런 끔찍한?


Richard Levasseur의 게시물에 대한 의견은 추가 옵션 인 Accept헤더 (14.1 절)를 상기시킵니다. oEmbed 스펙이 나왔을 때 HTTP를 사용하여 왜 완전히 수행되지 않았는지 궁금해하고 대안을 작성했습니다.

300 Multiple ChoicesLink초기 순진 HTTP에 대한 헤더와 HTML 페이지 GET, 오히려 사용 범위보다, 새로운 페이징 관계가 사용 정의가 Accept헤더를. 후속 HTTP 요청은 다음과 같습니다.

GET /db/questions HTTP/1.1
Host: paged.collection.example
Accept: application/json;PagingSpec=1.0;page=1

Accept헤더는 해당 유형 (페이지 번호)에 대한 허용 내용 유형 (당신의 JSON 리턴), 플러스 확장 매개 변수를 정의 할 수 있습니다. 내 oEmbed 쓰기에서 내 노트를 찢어 내면 (여기에 링크 할 수 없으며 내 프로파일에 나열 할 것입니다) page매개 변수의 의미 를 재정의해야 할 경우 매우 명시 적이며 여기에 사양 / 관련 버전을 제공 할 수 있습니다 앞으로.


1
+1 링크 헤더이지만 일반적인 첫 번째, 이전, 다음, 마지막 릴뿐만 아니라 RFC5005의 이전 아카이브, 다음 아카이브 및 현재를 권장합니다.
Joseph Holsten

> / db / questions에 대한 요청에서 각 페이지로 이동하는 방법을 지정하는 링크 헤더가있는 300 개의 객관식을 반환합니다 . 목표는 네트워크 요청을 최소화하는 것입니다. 첫 번째 요청은 결과를 제공해야하며 결국에는 필요한 데이터를 제공하는 더 많은 요청에 대한 링크가 아닙니다.
Stijn de Witt

4

편집하다:

그것에 대해 조금 더 생각한 후에 Range 헤더가 페이지 매김에 적합하지 않다는 것에 동의합니다. 논리는 Range 헤더는 응용 프로그램이 아니라 서버의 응답을위한 것입니다. 100MB의 결과를 제공했지만 서버 (또는 클라이언트)가 한 번에 1MB 만 처리 할 수 ​​있다면 Range 헤더의 용도입니다.

또한 리소스의 하위 집합이 자체 리소스 (관계형 대수와 유사)라는 의견에 동의하므로 URL로 표현할 가치가 있습니다.

그래서 기본적으로 헤더 사용에 대한 원래의 대답 (아래)을 언급합니다.


나는 당신이 당신의 자신의 질문에 대답했다고 생각합니다. 콘텐츠 범위와 함께 200 또는 206을 반환하고 선택적으로 쿼리 매개 변수를 사용하십시오. 사용자 에이전트와 컨텐츠 유형을 스니핑하고 그에 따라 쿼리 매개 변수를 확인합니다. 그렇지 않으면 범위 헤더가 필요합니다.

본질적으로 상충되는 목표가 있습니다. 사용자가 브라우저를 사용하여 탐색 (맞춤 헤더를 쉽게 허용하지 않음)하거나 헤더를 설정할 수있는 특수 클라이언트를 사용하도록 강요 할 수 있습니다 (탐색 할 수 없음).

요청에 따라 특수 클라이언트를 제공 할 수 있습니다-일반 브라우저처럼 보이는 경우 페이지를 렌더링하고 필요한 헤더를 설정하는 작은 ajax 앱을 보내십시오.

물론, URL이 이런 종류의 일에 필요한 모든 상태를 포함해야하는지에 대한 논쟁도 있습니다. 일부에서는 헤더를 사용하여 범위를 지정하는 것이 "안식하지 않은"것으로 간주 될 수 있습니다.

또한 서버가 "Can-Specify : Header1, header2"헤더로 응답 할 수 있고 웹 브라우저가 UI를 제공하여 사용자가 원하는 경우 값을 채울 수 있다면 좋을 것입니다.


답변 주셔서 감사합니다. 나는 그 주제에 대해 생각했지만 두 번째 의견을 얻기를 바랐다. 헤더 인수에 대한 포인터가 생겼습니까?
Karl Guertin

여기에 내가 북마크 한 유일한 것이 있습니다 (주석의 토론 참조) : barelyenough.org/blog/2008/05/versioning-rest-web-services 또 다른 사이트는 Ruby의 .json, .xml ,. 요청의 컨텐츠 유형 몇 가지 예는 다음과 같습니다. * language-URL에 넣으면 링크를 다른 국가로 보내면 잘못된 언어로 렌더링됩니다. 페이지 매김-헤더에 넣으면 사람들이 보는 것과 연결할 수 없습니다.
Richard Levasseur

* content-type : 언어 및 페이지 매김 문제의 조합-URL에있는 경우 클라이언트가 해당 컨텐츠 유형을 지원하지 않는 경우 (예 : .ajax 및 .html 확장자)? 반대로 URL에 해당 내용 유형이 없으면 동일한 표현을 제공 할 수 없습니다. "new ajax site! example.com/cool.ajax"vs "cool article here : example.com/article.ajax#id=123".
Richard Levasseur 2016 년

2
URL에 들어가는 지 여부는 IMO가 무엇인지에 달려 있습니다. 저의 일반적인 규칙은 구체적인 자원 (특정 상태, 자원 선택 또는 불연속 결과의 자원)을 식별하면 URL에 들어갑니다. 검색어, 페이지 매김 및 편안한 거래가 이에 대한 좋은 예입니다. 추상 표현을 구체적인 표현으로 변환하는 데 필요한 것이 있으면 헤더로 이동합니다. 인증 정보 및 콘텐츠 유형이 이에 대한 좋은 예입니다.
Richard Levasseur 2016 년

URL의 쿼리 문자열을 지정된 리소스를 쿼리하는 옵션으로 생각합니다.
wprl

3

Atom Feed Protocol과 같은 모델을 사용하면 정상적인 HTTP 모델 콜렉션과이를 조작하는 방법 (제대로 WebDAV를 의미 함)이 있으므로이 모델을 사용하는 것이 좋습니다.

콜렉션 모델 및 REST 조작을 정의 하는 Atom Publishing Protocol이 있으며 RFC 5005-Feed Paging and Archiving 을 사용하여 대규모 콜렉션을 페이징 할 수 있습니다 .

Atom XML에서 JSON 컨텐츠로 전환해도 아이디어에 영향을 미치지 않습니다.


3

여기서 진짜 문제는 413-Requested Entity Too Large에 직면했을 때 자동 리디렉션을 수행하는 방법을 알려주는 사양이 없다는 것입니다.

나는 최근 에이 같은 문제로 어려움을 겪고 있었고 RESTful Web Services 책 에서 영감을 찾았습니다 . 개인적으로 헤더 요구 사항으로 인해 206이 적절하지 않다고 생각합니다. 저의 생각은 저를 300으로 이끌어주었습니다. 다른 MIME 유형에 더 적합하다고 생각했기 때문에 377 페이지 부록 B의 주제에 대해 Richardson과 Ruby가 말한 내용을 찾아 보았습니다. 표현은 기본적으로 300이어야한다는 개념을 무시하고 200으로 다시 보냅니다.

그것은 또한 우리가 원자에서 가지고있는 다음 자원들에 대한 링크라는 개념과 함께 떨립니다. 내가 구현 한 솔루션은 내가 보내고 있던 json 맵에 "다음"및 "이전"키를 추가하여 수행했습니다.

나중에 내가 생각하기 시작한 것은 307-/ db / questions / 1,25와 같은 링크로 307-임시 리디렉션을 보내는 것입니다.이 링크는 원래 URI를 표준 자원 이름으로 남겨 둡니다. 적절하게 명명 된 종속 자원. 이것은 413에서보고 싶은 행동이지만 307은 좋은 타협으로 보입니다. 실제로 코드에서 아직 시도하지 않았습니다. 더 좋은 방법은 리디렉션이 가장 최근에 질문 한 실제 ID가 포함 된 URL로 리디렉션하는 것입니다. 예를 들어, 각 질문에 정수 ID가 있고 시스템에 100 개의 질문이 있고 가장 최근에 열 개의 질문을 표시하려는 경우 / db / questions에 대한 요청은 / db / questions / 100,91로 307해야합니다.

질문 해 주셔서 감사합니다. 당신은 내가 그것에 대해 생각하는 데 며칠을 보낸 견과가 아니라고 확인했습니다.


307은 307보다이 점에서 더 낫습니다. 307은 클라이언트가 예상 한대로 원래 URL이 곧 응답하기 시작할 것임을 의미합니다.
니콜라스 생크

RFC 7231은 HTTP 상태 코드 413을 Payload Too Large 로 참조 하고이 코드를 잠재적 인 응답 크기가 아닌 요청 크기와 관련시킵니다.
beawolf

1

Range헤더 를 감지하고 존재하는 경우 Dojo를 모방하고 존재하지 않는 경우 Atom을 모방 할 수 있습니다. 이것은 유스 케이스를 깔끔하게 나눕니다. 애플리케이션의 REST 쿼리에 응답하는 경우 Range헤더 로 형식화 될 것으로 예상됩니다 . 일반 브라우저에 응답하는 경우 페이징 링크를 반환하면 도구를 통해 컬렉션을 쉽게 탐색 할 수 있습니다.


1

범위 헤더의 큰 문제 중 하나는 많은 회사 프록시가이를 필터링한다는 것입니다. 대신 쿼리 매개 변수를 사용하는 것이 좋습니다.



0

가장 좋은 방법은 범위를 쿼리 매개 변수로 포함하는 것입니다. 예를 들어, GET / db / questions /? date> mindate & date <maxdate 입니다. 조회 매개 변수없이 / db / questions /에 GET을 수행하면 Location : / db / questions /? query-parameters-to-retrieve-the-default-page 와 함께 303을 리턴 하십시오 . 그런 다음 API를 사용하는 사람이 컬렉션에 대한 통계를 얻는 데 사용하는 다른 URL을 제공하십시오 (예 : 전체 컬렉션을 원하는 경우 사용할 쿼리 매개 변수).


0

이 목적으로 Range 헤더를 사용할 수는 있지만 그 의도는 아닙니다. 비정상적인 연결을 처리하고 데이터를 제한하기 위해 설계된 것으로 보입니다 (따라서 무언가가 없거나 크기가 너무 커서 처리하기 위해 클라이언트가 요청의 일부를 요청할 수 있음). 통신 계층에서 다른 목적으로 사용되는 것으로 페이지 매김을 해킹하고 있습니다. 페이지 매김을 처리하는 "적절한"방법은 반환하는 유형입니다. 질문 객체를 반환하는 대신 새로운 유형을 반환해야합니다.

따라서 질문이 다음과 같은 경우 :

<questions> <question index=1></question> <question index=2></question> ... </questions>

새로운 유형은 다음과 같습니다.

<questionPage> <startIndex>50</startIndex> <returnedCount>10</returnedCount> <totalCount>1203</totalCount> <questions> <question index=50></question> <question index=51></question> .. </questions> <questionPage>

물론 미디어 유형을 제어하므로 "페이지"를 필요에 맞는 형식으로 만들 수 있습니다. 일반적인 것이면 클라이언트에 단일 파서가있어 모든 유형에 대해 동일한 페이징을 처리 할 수 ​​있습니다. 나는 그것이 다른 것에 대한 Range 매개 변수를 혼란시키는 것이 아니라 HTTP 사양의 정신에 있다고 생각합니다.

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