เพจในคอลเลกชันที่เหลือ


134

ฉันสนใจที่จะเปิดเผยอินเทอร์เฟซ REST โดยตรงกับคอลเล็กชันของเอกสาร JSON (คิดว่าCouchDBหรือPersevere ) ปัญหาที่ฉันพบคือวิธีจัดการการGETดำเนินการบนคอลเลกชันรูทหากคอลเลกชันมีขนาดใหญ่

ตัวอย่างเช่นแกล้งทำเป็นว่าฉันกำลังเปิดเผยQuestionsตารางของ StackOverflow ซึ่งแต่ละแถวจะแสดงเป็นเอกสาร (ไม่ใช่ว่าจำเป็นต้องมีตารางดังกล่าวเป็นเพียงตัวอย่างที่เป็นรูปธรรมของชุด 'เอกสาร' ที่มีขนาดใหญ่) คอลเลกชันจะทำให้สามารถดูได้ที่/db/questionsกับ API CRUD ปกติGET /db/questions/XXX, PUT /db/questions/XXX, POST /db/questionsอยู่ในการเล่น วิธีมาตรฐานในการรับคอลเลกชันทั้งหมดคือGET /db/questionsแต่ถ้าการทิ้งแต่ละแถวเป็นออบเจ็กต์ JSON อย่างไร้เดียงสาคุณจะได้รับการดาวน์โหลดที่ค่อนข้างใหญ่และทำงานได้มากในส่วนของเซิร์ฟเวอร์

วิธีแก้ปัญหาคือการเพจ Dojo มีการแก้ไขปัญหานี้ในของJsonRestStoreผ่านทางส่วนขยาย RFC2616 สอดคล้องฉลาดของใช้ส่วนหัวกับหน่วยช่วงที่กำหนดเองRange itemsผลลัพธ์คือ a 206 Partial Contentที่ส่งคืนเฉพาะช่วงที่ร้องขอ ข้อได้เปรียบของวิธีนี้เหนือพารามิเตอร์การค้นหาคือมันจะทิ้งสตริงการสืบค้นไว้สำหรับ ... คิวรี (เช่นGET /db/questions/?score>200หรือบางครั้งและใช่ว่าจะเข้ารหัส%3E)

แนวทางนี้ครอบคลุมพฤติกรรมที่ฉันต้องการอย่างสมบูรณ์ ปัญหาคือRFC 2616ระบุว่าในการตอบสนอง 206 (เน้นของฉัน):

คำขอต้องมีรวมถึงข้อมูลส่วนหัวช่วง ( ส่วน 14.35 ) แสดงให้เห็นช่วงที่ต้องการและอาจจะรวมถึงข้อมูลส่วนหัวถ้าช่วง ( ส่วน 14.27 ) เพื่อให้เงื่อนไขการร้องขอ

สิ่งนี้สมเหตุสมผลในบริบทของการใช้ส่วนหัวมาตรฐาน แต่เป็นปัญหาเพราะฉันต้องการให้คำตอบ 206 เป็นค่าเริ่มต้นในการจัดการกับลูกค้าที่ไร้เดียงสา / คนที่สุ่มสำรวจ

ฉันได้ดูรายละเอียดเกี่ยวกับ RFC เพื่อหาวิธีแก้ปัญหา แต่ไม่พอใจกับวิธีแก้ปัญหาของฉันและสนใจที่ SO จะจัดการกับปัญหา

ความคิดที่ฉันมี:

  • กลับมา200พร้อมContent-Rangeส่วนหัว! - ฉันไม่คิดว่าสิ่งนี้ผิด แต่ฉันต้องการถ้าตัวบ่งชี้ที่ชัดเจนกว่านี้ว่าการตอบสนองเป็นเพียงเนื้อหาบางส่วน
  • Return400 Range Required - ไม่มีรหัสตอบกลับพิเศษ 400 สำหรับส่วนหัวที่ต้องการดังนั้นจึงต้องใช้ข้อผิดพลาดเริ่มต้นและอ่านด้วยมือ นอกจากนี้ยังทำให้การสำรวจผ่านเว็บเบราว์เซอร์ (หรือไคลเอนต์อื่น ๆ เช่น Resty) ยากขึ้น
  • ใช้พารามิเตอร์การค้นหา - วิธีการมาตรฐาน แต่ฉันหวังว่าจะอนุญาตการสืบค้น a la Persevere และสิ่งนี้จะตัดลงในเนมสเปซการสืบค้น
  • แค่กลับ206! - ฉันคิดว่าลูกค้าส่วนใหญ่จะไม่ประหลาดใจ แต่ฉันไม่อยากต่อต้าน MUST ใน RFC
  • ขยายสเป็ค! Return266 Partial Content - มีพฤติกรรมเหมือน 206 แต่ตอบสนองต่อคำร้องขอที่ต้องไม่มีRangeส่วนหัว ฉันคิดว่า 266 นั้นสูงพอที่ฉันไม่ควรเจอปัญหาการชนกันและมันก็สมเหตุสมผลสำหรับฉัน แต่ฉันไม่ชัดเจนว่านี่ถือเป็นข้อห้ามหรือไม่

ฉันคิดว่านี่เป็นปัญหาที่พบได้บ่อยและฉันอยากเห็นสิ่งนี้เกิดขึ้นในแบบพฤตินัยดังนั้นฉันหรือคนอื่นจะไม่คิดค้นล้อใหม่

วิธีใดที่ดีที่สุดในการแสดงคอลเล็กชันทั้งหมดผ่าน HTTP เมื่อคอลเล็กชันมีขนาดใหญ่


21
ว้าวเป็นตัวอย่างที่ดีของคำถามที่เคยคิดอย่างจริงจังมาก่อน
Heiko Rupp


2
เท่าที่วิธีการของ Dojo ในการใช้ส่วนหัวช่วงแม้จะยอมรับช่วงช่วยให้การขยายจากทั้งหมดที่ฉันสามารถบอก EBNF สำหรับช่วงไม่ได้: tools.ietf.org/html/rfc2616#section-14.35.2 ข้อมูลจำเพาะระบุRange = "Range" ":" ranges-specifierว่าส่วนหลังในtools.ietf.org/html/rfc2616#section-14.35.1อธิบายเพียงว่า "byte-range-specifier" ซึ่งต้องขึ้นต้นด้วย "bytes-unit" ซึ่งกำหนดเป็นสตริง "bytes ".
Brett Zamir

2
Content-Rangeส่วนหัวใช้กับร่างกาย (สามารถนำมาใช้กับการร้องขอเมื่ออัปโหลดไฟล์ขนาดใหญ่ ฯลฯ หรือการตอบสนองเมื่อมีการดาวน์โหลด) Rangeส่วนหัวจะใช้ในการขอบางช่วง หนึ่งควรตอบกลับ206เมื่อRangeรวมส่วนหัวในคำขอ ถ้ามันไม่ได้ตอบสนองยังอาจรวมถึงContent-Rangeส่วนหัว 200แต่รหัสการตอบสนองที่ควรจะเป็น ส่วนหัวนี้ดูเหมือนจะเหมาะสำหรับการเพจ
Stijn de Witt

1
แต่ RFC 2616 เองบอกว่า "การใช้งาน HTTP / 1.1 อาจละเว้นช่วงที่ระบุโดยใช้หน่วยอื่น" ดังนั้นจึงเป็นแนวทางปฏิบัติที่ดีในการใช้ส่วนหัวของช่วงสำหรับการแบ่งหน้าหรือไม่? เพราะมันอาจทำให้ความสามารถในการทำงานร่วมกันลดลง
chetan choulwar

คำตอบ:


23

ความรู้สึกของฉันคือส่วนขยายช่วง HTTP ไม่ได้ออกแบบมาสำหรับกรณีการใช้งานของคุณดังนั้นคุณไม่ควรลอง การตอบกลับบางส่วนเป็นนัย206และ206จะต้องส่งเมื่อลูกค้าร้องขอเท่านั้น

คุณอาจต้องการพิจารณาแนวทางที่แตกต่างออกไปเช่นวิธีที่ใช้ใน Atom (ซึ่งการแสดงโดยการออกแบบอาจเป็นเพียงบางส่วนและส่งกลับมาพร้อมกับสถานะ200และลิงก์เพจที่อาจเกิดขึ้น) ดูRFC 4287และRFC 5005


14
การใช้งาน Dojo เป็นไปตามข้อกำหนดอย่างสมบูรณ์ หากเซิร์ฟเวอร์ไม่เข้าใจitemsหน่วยช่วงเซิร์ฟเวอร์จะส่งคืนการตอบสนองทั้งหมด ฉันคุ้นเคยกับ Atom แต่นั่นไม่ใช่วิธีแก้ปัญหาทั่วไปสำหรับ Rest paging นี่ไม่ใช่วิธีแก้ปัญหาสำหรับกรณีเดียว แต่เป็นวิธีแก้ปัญหาทั่วไปมากกว่า เอกสาร / คอลเล็กชันบางรายการไม่พอดีกับโมเดล Atom และไม่มีเหตุผลที่จะบังคับใช้เว้นแต่จำเป็น
Karl Guertin

1
@KarlGuertin เห็นด้วย น่าเสียดายที่นี่เป็นคำตอบที่ได้รับการยอมรับเพราะดูเหมือนว่าหลาย ๆ คนในชุมชนจะยอมรับRangeและContent-Rangeเพื่อวัตถุประสงค์ในการเพจ
Stijn de Witt

34

ฉันไม่ค่อยเห็นด้วยกับพวกคุณบางคน ฉันทำงานมาหลายสัปดาห์เกี่ยวกับคุณสมบัตินี้สำหรับบริการ REST ของฉัน สิ่งที่ฉันทำมันง่ายมาก โซลูชันของฉันเหมาะสมกับสิ่งที่คน REST เรียกว่าคอลเล็กชันเท่านั้น

ลูกค้าต้องใส่ส่วนหัว "ช่วง" เพื่อระบุว่าเขาต้องการส่วนใดของคอลเลกชันหรือไม่เช่นนั้นก็พร้อมที่จะจัดการข้อผิดพลาด 413 ENTITY TOO LARGE เมื่อคอลเล็กชันที่ร้องขอมีขนาดใหญ่เกินกว่าที่จะเรียกข้อมูลในการเดินทางไปกลับเดียว

เซิร์ฟเวอร์ส่งการตอบกลับเนื้อหาบางส่วน 206 ส่วนโดยส่วนหัวของช่วงเนื้อหาจะระบุว่าส่วนใดของทรัพยากรถูกส่งไปและส่วนหัว ETag เพื่อระบุเวอร์ชันปัจจุบันของคอลเล็กชัน ฉันมักจะใช้ ETag แบบ Facebook {last_modification_timestamp} - {resource_id} และฉันคิดว่า ETag ของคอลเล็กชันเป็นทรัพยากรที่แก้ไขล่าสุดที่มีอยู่

ในการขอบางส่วนของคอลเลกชันลูกค้าต้องใช้ส่วนหัว "ช่วง" และเติมส่วนหัว "If-Match" ด้วย ETag ของคอลเล็กชันที่ได้รับจากคำขอที่ดำเนินการก่อนหน้านี้เพื่อรับส่วนอื่น ๆ ของคอลเล็กชันเดียวกัน เซิร์ฟเวอร์สามารถตรวจสอบได้ว่าคอลเลกชันไม่ได้เปลี่ยนแปลงก่อนที่จะส่งส่วนที่ร้องขอ หากมีเวอร์ชันที่ใหม่กว่าอยู่การตอบกลับ 412 PRECONDITION FAILED จะถูกส่งกลับเพื่อเชิญชวนให้ไคลเอ็นต์เรียกคืนคอลเล็กชันตั้งแต่เริ่มต้น สิ่งนี้จำเป็นเนื่องจากอาจหมายความว่าอาจมีการเพิ่มหรือลบทรัพยากรบางส่วนก่อนหรือหลังส่วนที่ร้องขอในปัจจุบัน

ฉันใช้ ETag / If-Match ควบคู่กับ Last-Modified / If-Unmodified-Since เพื่อเพิ่มประสิทธิภาพแคช เบราว์เซอร์และพร็อกซีอาจอาศัยหนึ่งหรือทั้งสองอย่างสำหรับอัลกอริทึมการแคช

ฉันคิดว่า URL ควรสะอาดเว้นแต่จะรวมคำค้นหา / ตัวกรอง หากคุณคิดเกี่ยวกับเรื่องนี้การค้นหาไม่ได้เป็นเพียงมุมมองบางส่วนของคอลเล็กชัน แทนที่จะเป็นรถยนต์ / ค้นหา? q = ประเภท URL ของ BMW เราควรเห็นรถยนต์มากขึ้น? ผู้ผลิต = BMW


คุณหมายถึง 416 "ช่วงที่ขอไม่พอใจ" หรือ "413" ขอเอนทิตีใหญ่เกินไปหรือเปล่า

1
@Mohamed ฉันคิดว่าคุณหมายถึงIf-Unmodified-Sinceซึ่งสอดคล้องกับตัวแปร E-Tag มากกว่าIf-Match If-Modified-Sinceอย่างไรก็ตามคุณอาจพิจารณาลบข้อ จำกัด นี้ได้โดยขึ้นอยู่กับกรณีการใช้งานของคุณ สมมติว่าคุณมีคอลเล็กชันที่เพิ่มขึ้นจากด้านบนเท่านั้น (เช่นคอลเล็กชันสไตล์ "ใหม่ล่าสุดอันดับแรก") สิ่งที่เลวร้ายที่สุดที่อาจเกิดขึ้นได้หากคอลเล็กชันนั้นเปลี่ยนไประหว่างคำขอคือผู้ใช้ที่เข้าชมคอลเล็กชันจะเห็นรายการสองครั้ง (ซึ่งในตัวมันเองก็เป็นข้อมูลที่มีประโยชน์เช่นกันมันบอกผู้ใช้ว่าคอลเล็กชันมีการเปลี่ยนแปลง)
Evgeniy Berezovsky

21
413 คือ "Request Entity Too Large" ไม่ใช่ "Requested Entity Too Large" หมายความว่าขนาดคำขอของคุณตัวอย่างเช่นเมื่ออัปโหลดไฟล์มีขนาดใหญ่เกินกว่าที่เซิร์ฟเวอร์จะดำเนินการ ดังนั้นการใช้เพื่อสิ่งนี้ดูเหมือนจะไม่เหมาะสมอย่างสมบูรณ์
user247702

@ Mohamed ฉันรู้ว่ามันเป็นคำถามเก่า แต่ถ้า ETag ของคอลเลกชันเป็น ETag ของทรัพยากรที่แก้ไขล่าสุดที่คอลเลกชันมีอยู่ควรใช้ค่าของส่วนหัว If-Match ใดเมื่อแก้ไขทรัพยากรหนึ่งในคอลเล็กชัน การใช้ค่าของ ETag ที่ส่งคืนมาพร้อมกับคอลเล็กชันนั้นไม่ถูกต้องเนื่องจากไคลเอ็นต์จะสามารถแก้ไขทรัพยากรได้แม้ว่าเขาจะไม่เห็นสถานะสุดท้ายของทรัพยากรก็ตาม
Mickael Marrache

9
413ผมเห็นด้วยอย่างยิ่งเกี่ยวกับการใช้ นี่คือรหัสข้อผิดพลาดซึ่งหมายความว่าไคลเอนต์กำลังส่งบางสิ่งที่เซิร์ฟเวอร์ปฏิเสธที่จะยอมรับเนื่องจากขนาด ไม่ใช่ทางอื่น! ดูtools.ietf.org/html/rfc7231#section-6.5.11 (โปรดทราบว่ามันระบุว่าrequest payload ไม่ใช่response payload)!
exhuma

7

คุณยังสามารถส่งคืนAccept-RangesและContent-Rangesใช้200รหัสตอบกลับได้ ส่วนหัวการตอบกลับทั้งสองนี้ให้ข้อมูลเพียงพอที่จะสรุปข้อมูลเดียวกันกับที่206รหัสตอบกลับให้ไว้อย่างชัดเจน

ผมจะใช้Rangeสำหรับการแบ่งหน้าและมีมันก็กลับสำหรับธรรมดา200GET

สิ่งนี้ให้ความรู้สึกผ่อนคลาย100% และไม่ทำให้การเรียกดูยากขึ้น

แก้ไข: ฉันเขียนบล็อกโพสต์เกี่ยวกับเรื่องนี้: http://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html


5

หากมีคำตอบมากกว่าหนึ่งหน้าและคุณไม่ต้องการเสนอทั้งคอลเลคชันพร้อมกันหมายความว่ามีหลายทางเลือกใช่หรือไม่?

ในการร้องขอให้/db/questionsส่งคืน300 Multiple Choicesพร้อมกับLinkส่วนหัวที่ระบุวิธีเข้าถึงแต่ละเพจเช่นเดียวกับออบเจ็กต์ JSON หรือเพจ HTML ที่มีรายการ URL

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ส่วนหัว หากเป็นผู้ใช้ที่เรียกดูด้วยตนเองอาจเป็นเพจ HTML ที่มีลิงก์ไปยังทรัพยากรรูทพิเศษ "เพจ" ที่สามารถจัดการการแสดงผลเพจนั้นตาม URL ได้? /humanpage/1/db/questionsหรืออะไรที่น่ากลัวแบบนั้น?


ความคิดเห็นในโพสต์ของ Richard Levasseur ทำให้ฉันนึกถึงตัวเลือกเพิ่มเติม: Acceptส่วนหัว (ส่วนที่ 14.1) ย้อนกลับไปเมื่อข้อมูลจำเพาะ oEmbed ออกมาฉันสงสัยว่าเหตุใดจึงไม่ได้ใช้ HTTP ทั้งหมดและเขียนทางเลือกโดยใช้

เก็บ300 Multiple Choicesที่Linkส่วนหัวและหน้า HTML สำหรับ HTTP ไร้เดียงสาเริ่มต้น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 Multiple Choices พร้อมส่วนหัวลิงก์ที่ระบุวิธีเข้าถึงแต่ละหน้า [.. ] ปัญหานั้น (และด้วยการออกแบบ REST ที่บริสุทธิ์ที่สุด) คือการฆ่าเพื่อเวลาแฝง เป้าหมายคือเพื่อลดคำขอเครือข่าย คำขอแรกนั้นควรให้ผลลัพธ์ไม่ใช่ลิงก์ไปยังคำขอเพิ่มเติมซึ่งจะให้ข้อมูลที่เราต้องการในที่สุด
Stijn de Witt

4

แก้ไข:

หลังจากคิดถึงเรื่องนี้อีกเล็กน้อยฉันมีแนวโน้มที่จะยอมรับว่าส่วนหัวของช่วงไม่เหมาะสมกับการแบ่งหน้า ตรรกะเป็นส่วนหัวของช่วงมีไว้สำหรับการตอบสนองของเซิร์ฟเวอร์ไม่ใช่แอปพลิเคชัน หากคุณให้ผลลัพธ์ 100 เมกะไบต์ แต่เซิร์ฟเวอร์ (หรือไคลเอนต์) สามารถประมวลผลได้ครั้งละ 1 เมกะไบต์เท่านั้นนั่นคือสิ่งที่ส่วนหัวของช่วงมีไว้สำหรับ

ฉันยังมีความเห็นว่าทรัพยากรส่วนย่อยเป็นทรัพยากรของตัวเอง (คล้ายกับพีชคณิตเชิงสัมพันธ์) ดังนั้นจึงสมควรได้รับการนำเสนอใน URL

โดยพื้นฐานแล้วฉันจะอ่านคำตอบเดิมของฉัน (ด้านล่าง) เกี่ยวกับการใช้ส่วนหัว


ฉันคิดว่าคุณตอบคำถามของคุณเองไม่มากก็น้อย - ส่งคืน 200 หรือ 206 พร้อมช่วงเนื้อหาและเลือกใช้พารามิเตอร์การสืบค้น ฉันจะดมกลิ่นตัวแทนผู้ใช้และประเภทเนื้อหาและตรวจสอบพารามิเตอร์เคียวรีขึ้นอยู่กับสิ่งเหล่านั้น มิฉะนั้นต้องใช้ส่วนหัวของช่วง

คุณมีเป้าหมายที่ขัดแย้งกันเป็นหลัก - ให้ผู้คนใช้เบราว์เซอร์เพื่อสำรวจ (ซึ่งไม่อนุญาตให้ใช้ส่วนหัวที่กำหนดเองได้ง่ายๆ) หรือบังคับให้ผู้ใช้ใช้ไคลเอนต์พิเศษที่สามารถกำหนดส่วนหัวได้ (ซึ่งไม่ให้พวกเขาสำรวจ)

คุณสามารถจัดหาไคลเอนต์พิเศษให้กับพวกเขาได้ตามคำขอหากดูเหมือนเบราว์เซอร์ธรรมดาให้ส่งแอป ajax ขนาดเล็กที่แสดงผลหน้าและตั้งค่าส่วนหัวที่จำเป็น

แน่นอนว่ายังมีการถกเถียงกันว่า URL ควรมีสถานะที่จำเป็นทั้งหมดสำหรับสิ่งนี้หรือไม่ การระบุช่วงโดยใช้ส่วนหัวอาจถือได้ว่าบางคน "ไม่สงบ"

นอกจากนี้จะเป็นการดีหากเซิร์ฟเวอร์สามารถตอบสนองด้วยส่วนหัว "Can-ระบุ: Header1, header2" และเว็บเบราว์เซอร์จะแสดง UI เพื่อให้ผู้ใช้สามารถกรอกค่าได้หากต้องการ


ขอบคุณสำหรับการตอบกลับ ฉันคิดเกี่ยวกับหัวข้อนี้ แต่หวังว่าจะได้รับความคิดเห็นที่สอง มีตัวชี้สำหรับอาร์กิวเมนต์ส่วนหัวหรือไม่?
Karl Guertin

นี่เป็นเว็บไซต์เดียวที่ฉันบุ๊กมาร์กไว้ (ดูการสนทนาในความคิดเห็น): barelyenough.org/blog/2008/05/versioning-rest-web-services ไซต์อื่นที่เกี่ยวข้องกับการใช้. json, .xml,. ประเภทเนื้อหาของคำขอ ตัวอย่างบางส่วน: * ภาษา - การใส่ไว้ใน URL หมายถึงการส่งลิงก์ไปยังประเทศอื่นจะทำให้เป็นภาษาที่ไม่ถูกต้อง * การแบ่งหน้า - การใส่ไว้ในส่วนหัวหมายความว่าคุณไม่สามารถเชื่อมโยงบุคคลกับสิ่งที่คุณเห็นได้
Richard Levasseur

* content-type: การรวมกันของภาษาและปัญหาการแบ่งหน้า - หากอยู่ใน url จะเกิดอะไรขึ้นถ้าไคลเอนต์ไม่รองรับเนื้อหาประเภทนั้น (เช่นนามสกุล. Ajax และ. html) ในทางกลับกันหากไม่มีประเภทเนื้อหานั้นใน url คุณไม่สามารถมั่นใจได้ว่าจะได้รับการแสดงแบบเดียวกัน "ไซต์ ajax ใหม่! example.com/cool.ajax" เทียบกับ "บทความเด็ดที่นี่: example.com/article.ajax#id=123"
Richard Levasseur

2
IMO ไม่ว่าจะอยู่ใน URL หรือไม่ขึ้นอยู่กับว่ามันคืออะไร กฎทั่วไปของฉันคือหากจะระบุทรัพยากรที่เป็นรูปธรรม (ไม่ว่าจะเป็นทรัพยากรในสถานะเฉพาะการเลือกทรัพยากรหรือผลลัพธ์ที่ไม่ต่อเนื่อง) จะอยู่ใน URL คำค้นหาการแบ่งหน้าและธุรกรรมที่ไม่สงบเป็นตัวอย่างที่ดีของสิ่งนี้ หากสิ่งที่จำเป็นในการเปลี่ยนการแสดงนามธรรมเป็นการแสดงที่เป็นรูปธรรมสิ่งนั้นจะอยู่ในส่วนหัว ข้อมูลรับรองความถูกต้องและประเภทเนื้อหาเป็นตัวอย่างที่ดีของสิ่งนี้
Richard Levasseur

ฉันคิดว่าสตริงการสืบค้นใน URL เป็นตัวเลือกสำหรับการสืบค้นทรัพยากรที่ระบุ
wprl

3

คุณอาจพิจารณาใช้โมเดลบางอย่างเช่น Atom Feed Protocol เนื่องจากมีโมเดล HTTP ที่ดีของคอลเล็กชันและวิธีจัดการ (โดยที่บ้าหมายถึง WebDAV)

มีAtom Publishing Protocolซึ่งกำหนดรูปแบบการรวบรวมและการดำเนินการ REST รวมทั้งคุณสามารถใช้RFC 5005 - Feed Paging และ Archivingเพื่อเลื่อนหน้าผ่านคอลเลกชันขนาดใหญ่

การเปลี่ยนจาก Atom XML เป็นเนื้อหา JSON ไม่ควรส่งผลต่อแนวคิดนี้


3

ฉันคิดว่าปัญหาที่แท้จริงที่นี่คือไม่มีอะไรในข้อมูลจำเพาะที่บอกเราถึงวิธีการเปลี่ยนเส้นทางอัตโนมัติเมื่อต้องเผชิญกับ 413 - เอนทิตีที่ร้องขอขนาดใหญ่เกินไป

ฉันกำลังต่อสู้กับปัญหาเดียวกันนี้เมื่อเร็ว ๆ นี้และผมมองหาแรงบันดาลใจในสงบ Web Servicesหนังสือ โดยส่วนตัวแล้วฉันไม่คิดว่า 206 เหมาะสมเนื่องจากข้อกำหนดส่วนหัว ความคิดของฉันทำให้ฉันได้ 300 ด้วย แต่ฉันคิดว่ามันมากกว่าสำหรับละครใบ้ประเภทต่างๆดังนั้นฉันจึงค้นหาสิ่งที่ริชาร์ดสันและรูบี้พูดในหัวข้อนี้ในภาคผนวก B หน้า 377 พวกเขาแนะนำว่าเซิร์ฟเวอร์เพียงแค่เลือกสิ่งที่ต้องการ เป็นตัวแทนและส่งกลับมาพร้อมกับ 200 โดยไม่สนใจแนวคิดที่ว่ามันควรจะเป็น 300

นอกจากนี้ยังมีแนวคิดเกี่ยวกับการเชื่อมโยงไปยังแหล่งข้อมูลถัดไปที่เรามีจากอะตอม วิธีแก้ปัญหาที่ฉันใช้คือเพิ่มคีย์ "next" และ "previous" ลงในแผนที่ json ที่ฉันส่งกลับมาและดำเนินการให้เสร็จสิ้น

ต่อมาฉันเริ่มคิดว่าสิ่งที่ต้องทำคือส่ง 307 - การเปลี่ยนเส้นทางชั่วคราวไปยังลิงก์ที่น่าจะเป็น / db / questions / 1,25 ซึ่งจะทำให้ URI ดั้งเดิมเป็นชื่อแหล่งข้อมูลที่ยอมรับได้ แต่จะช่วยให้คุณไปที่ ทรัพยากรรองที่มีชื่อเหมาะสม นี่เป็นพฤติกรรมที่ฉันอยากเห็นจาก 413 แต่ 307 ดูเหมือนจะเป็นการประนีประนอมที่ดี ยังไม่ได้ลองใช้รหัสจริงๆ สิ่งที่จะดีไปกว่านั้นคือการเปลี่ยนเส้นทางเพื่อเปลี่ยนเส้นทางไปยัง URL ที่มีรหัสจริงของคำถามที่ถามล่าสุด ตัวอย่างเช่นหากแต่ละคำถามมีรหัสจำนวนเต็มและมีคำถาม 100 ข้อในระบบและคุณต้องการแสดง 10 คำถามล่าสุดคำขอ / db / คำถามควรเป็น 307 ถึง / db / questions / 100,91

นี่เป็นคำถามที่ดีมากขอบคุณที่ถาม คุณยืนยันสำหรับฉันว่าฉันไม่ได้บ้าเพราะใช้เวลาคิดถึงเรื่องนี้มาหลายวัน


303 จะดีกว่าในเรื่องนี้ 307 307 หมายความว่า URL เดิมจะเริ่มตอบสนองในไม่ช้าตามที่ลูกค้าคาดหวัง
Nicholas Shanks

RFC 7231อ้างอิงรหัสสถานะ HTTP 413 เป็นPayload Too Largeและเชื่อมโยงรหัสนี้กับขนาดคำขอและไม่ใช่ขนาดการตอบสนองที่เป็นไปได้
beawolf

2

ปัญหาใหญ่อย่างหนึ่งของส่วนหัวของช่วงคือพร็อกซีขององค์กรจำนวนมากกรองพวกเขาออก ฉันขอแนะนำให้ใช้พารามิเตอร์การค้นหาแทน


2

ด้วยการตีพิมพ์ของrfc723x , หน่วยช่วงที่ไม่ได้จดทะเบียนทำไปกับคำแนะนำที่ชัดเจนในข้อมูลจำเพาะ พิจารณาrfc7233 (เลิกใช้ rfc2616):

" หน่วยช่วงใหม่ควรลงทะเบียนกับ IANA " (พร้อมกับการอ้างอิงไปยังHTTP Range Unit Registry )


1

คุณสามารถตรวจจับRangeส่วนหัวและเลียนแบบ Dojo ได้หากมีอยู่และเลียนแบบ Atom หากไม่มี สำหรับฉันแล้วสิ่งนี้แบ่งกรณีการใช้งานอย่างเรียบร้อย หากคุณกำลังตอบสนองต่อแบบสอบถาม REST จากแอปพลิเคชันของคุณคุณคาดว่าจะมีการจัดรูปแบบด้วยRangeส่วนหัว หากคุณกำลังตอบสนองต่อเบราว์เซอร์ทั่วไปหากคุณส่งคืนลิงก์เพจเครื่องมือนี้จะช่วยให้สามารถสำรวจคอลเล็กชันได้


0

สำหรับฉันแล้วดูเหมือนว่าวิธีที่ดีที่สุดในการทำเช่นนี้คือการรวมช่วงเป็นพารามิเตอร์การสืบค้น เช่นGET / db / questions /? date> mindate & date <maxdate . เมื่อได้รับการ / DB / คำถาม / มีพารามิเตอร์การค้นหาไม่กลับมา 303 กับ สถานที่: / จากนั้นระบุ URL ที่แตกต่างกันซึ่งใครก็ตามที่ใช้ API ของคุณเพื่อรับสถิติเกี่ยวกับคอลเล็กชัน (เช่นพารามิเตอร์การสืบค้นใดที่จะใช้หากต้องการให้คอลเล็กชันทั้งหมด)


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>

แน่นอนว่าคุณควบคุมประเภทสื่อของคุณได้ดังนั้นคุณจึงสามารถทำให้ "เพจ" เป็นรูปแบบที่เหมาะกับความต้องการของคุณได้ หากคุณสร้างเป็นสิ่งทั่วไปคุณสามารถมีตัววิเคราะห์เดียวบนไคลเอนต์เพื่อจัดการการเพจเหมือนกันสำหรับทุกประเภท ฉันคิดว่านั่นเป็นเจตนารมณ์ของข้อกำหนด HTTP มากกว่าที่จะหลอกพารามิเตอร์ Range สำหรับอย่างอื่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.