ทำความเข้าใจกับ REST: คำกริยารหัสข้อผิดพลาดและการตรวจสอบความถูกต้อง


602

ฉันกำลังมองหาวิธีห่อ APIs รอบฟังก์ชั่นเริ่มต้นในแอปพลิเคชันเว็บที่ใช้ PHP ฐานข้อมูลและ CMS ของฉัน

ฉันได้ดูไปรอบ ๆ และพบกรอบ "โครงกระดูก" หลายแห่ง นอกจากคำตอบในคำถามของฉันแล้วยังมีTonicกรอบ REST ที่ฉันชอบเพราะมันมีน้ำหนักเบามาก

ฉันชอบ REST ที่ดีที่สุดสำหรับความเรียบง่ายและต้องการสร้างสถาปัตยกรรม API ตามนั้น ฉันพยายามเข้าใจหลักการพื้นฐานและยังไม่เข้าใจอย่างถ่องแท้ ดังนั้นคำถามจำนวนหนึ่ง

1. ฉันเข้าใจถูกต้องหรือไม่

บอกว่าฉันมีทรัพยากร "ผู้ใช้" ฉันสามารถตั้งค่า URIs ได้หลายอย่างเช่น:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

นี่เป็นการแสดงที่ถูกต้องของสถาปัตยกรรม RESTful หรือไม่?

2. ฉันต้องการคำกริยามากกว่านี้

สร้างปรับปรุงและลบอาจจะเพียงพอในทางทฤษฎี แต่ในทางปฏิบัติฉันจะต้องใช้คำกริยามากขึ้น ฉันตระหนักดีเหล่านี้เป็นสิ่งที่อาจจะฝังตัวอยู่ในคำขอปรับปรุง แต่พวกเขาจะดำเนินการเฉพาะที่สามารถมีรหัสเฉพาะผลตอบแทนและฉันจะไม่ต้องการที่จะโยนพวกเขาทั้งหมดไปสู่การปฏิบัติอย่างใดอย่างหนึ่ง

ตัวอย่างที่ผู้ใช้คำนึงถึง ได้แก่ :

activate_login
deactivate_login
change_password
add_credit

ฉันจะแสดงการกระทำเช่นนั้นใน RESTful URL สถาปัตยกรรมอย่างไร

สัญชาตญาณของฉันจะทำการโทรไปยัง URL เช่น

/api/users/1/activate_login 

และคาดว่าจะมีรหัสสถานะกลับมา

ที่เบี่ยงเบนไปจากแนวคิดของการใช้คำกริยา HTTP คุณคิดอย่างไร?

3. วิธีคืนข้อความและรหัสข้อผิดพลาด

ส่วนที่ดีของความงามของ REST นั้นเกิดจากการใช้วิธี HTTP มาตรฐาน ในข้อผิดพลาดฉันปล่อยส่วนหัวด้วยรหัสสถานะข้อผิดพลาด 3xx, 4xx หรือ 5xx สำหรับคำอธิบายข้อผิดพลาดโดยละเอียดฉันสามารถใช้เนื้อความ (ใช่ไหม) จนถึงตอนนี้ดีมาก แต่จะเป็นวิธีใดในการส่งรหัสข้อผิดพลาดที่เป็นกรรมสิทธิ์ซึ่งมีรายละเอียดเพิ่มเติมในการอธิบายสิ่งที่ผิดพลาด (เช่น "ไม่สามารถเชื่อมต่อกับฐานข้อมูล" หรือ "เข้าสู่ระบบฐานข้อมูลผิด") ถ้าฉันใส่มันเข้าไปในร่างกายพร้อมกับข้อความฉันต้องแยกมันออกมาในภายหลัง มีส่วนหัวมาตรฐานสำหรับสิ่งนี้หรือไม่?

4. วิธีการตรวจสอบ

  • การรับรองความถูกต้องโดยใช้คีย์ API ตามหลักการ REST จะมีลักษณะอย่างไร
  • มีจุดแข็งที่จะต่อต้านการใช้เซสชันเมื่อตรวจสอบความถูกต้องของไคลเอนต์ REST นอกจากนั้นเป็นการละเมิดหลักการ REST ที่โจ่งแจ้งหรือไม่? :) (เพียงครึ่งล้อเล่นที่นี่การพิสูจน์ตัวตนจากเซสชันจะเล่นได้ดีกับโครงสร้างพื้นฐานที่มีอยู่ของฉัน)

13
@Daniel ขอบคุณสำหรับการแก้ไข "ฉันใช้คำกริยามากกว่านี้" เป็นการเล่นโดยเจตนา แต่ฉันจะทิ้งไว้อย่างที่เป็นอยู่ตอนนี้อ่านง่ายขึ้น :)
Pekka

1
BTW เกี่ยวกับคำอธิบายข้อผิดพลาด ฉันสิ้นสุดด้วยการใส่คำอธิบายข้อผิดพลาดในส่วนหัวของคำตอบ เพียงเพิ่มส่วนหัวชื่อ 'คำอธิบายข้อผิดพลาด'
Andrii Muzychuk

ดูเหมือนคำถามด้านความปลอดภัยของแอปพลิเคชัน ความปลอดภัยของแอพพลิเคชั่นไม่ได้เกี่ยวกับ REST
Nazar Merza

@NazarMerza เป็นคำถามเกี่ยวกับความปลอดภัยของแอปพลิเคชัน 1. , 2 และ 3. อย่างไร
Pekka

คำตอบ:


621

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


จุดที่ 1: ฉันเข้าใจถูกไหม

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


เมื่อจัดการกับCollection URI เช่น:http://example.com/resources/

  • GET : รายชื่อสมาชิกของคอลเลกชันพร้อมด้วย URIs สมาชิกของพวกเขาสำหรับการนำทางเพิ่มเติม ตัวอย่างเช่นแสดงรถยนต์ทุกคันเพื่อจำหน่าย

  • วาง : ความหมายที่กำหนดเป็น "แทนที่คอลเลกชันทั้งหมดด้วยคอลเล็กชันอื่น"

  • POST : สร้างรายการใหม่ในคอลเลกชันที่มีการกำหนด ID โดยอัตโนมัติโดยคอลเลกชัน โดยปกติแล้ว ID ที่สร้างขึ้นจะรวมเป็นส่วนหนึ่งของข้อมูลที่ส่งคืนโดยการดำเนินการนี้

  • ลบ : ความหมายที่กำหนดเป็น "ลบการเก็บทั้งหมด"


เมื่อจัดการกับURI ของสมาชิกเช่น:http://example.com/resources/7HOU57Y

  • GET : ดึงข้อมูลการเป็นตัวแทนของสมาชิกที่ได้รับการระบุของคอลเลกชันที่แสดงในประเภท MIME ที่เหมาะสม

  • วาง : อัปเดตสมาชิกที่ได้รับการระบุของคอลเลกชันหรือสร้างขึ้นด้วย ID ที่ระบุ

  • POST : ปฏิบัติต่อสมาชิกที่ได้รับการแต่งตั้งว่าเป็นกลุ่มของตนเองและสร้างกลุ่มย่อยใหม่

  • ลบ : ลบสมาชิกที่ได้รับการระบุของคอลเล็กชัน


จุดที่ 2: ฉันต้องการคำกริยามากกว่านี้

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

เปิดใช้งาน / ยกเลิกการเข้าสู่ระบบ : หากคุณกำลังสร้างเซสชันใหม่คุณอาจต้องการพิจารณา "เซสชั่น" เป็นทรัพยากร หากต้องการสร้างเซสชันใหม่ให้ใช้ POST http://example.com/sessions/กับข้อมูลประจำตัวในร่างกาย มันจะหมดอายุใช้ PUT หรือลบ (อาจจะขึ้นอยู่กับว่าคุณตั้งใจจะเก็บประวัติเซสชั่น) http://example.com/sessions/SESSION_IDเพื่อ

เปลี่ยนรหัสผ่าน:เวลานี้ทรัพยากรคือ "ผู้ใช้" คุณจะต้องใส่http://example.com/users/USER_IDรหัสผ่านด้วยรหัสผ่านเก่าและใหม่ในร่างกาย คุณกำลังดำเนินการกับทรัพยากร "ผู้ใช้" และรหัสผ่านการเปลี่ยนแปลงเป็นเพียงการร้องขอการปรับปรุง มันค่อนข้างคล้ายกับคำสั่ง UPDATE ในฐานข้อมูลเชิงสัมพันธ์

สัญชาตญาณของฉันจะทำการโทรไปยัง URL เช่น /api/users/1/activate_login

สิ่งนี้ขัดกับหลักการ REST ที่สำคัญมาก: การใช้กริยา HTTP ที่ถูกต้อง คำขอ GET ใด ๆ ไม่ควรมีผลข้างเคียงใด ๆ

ตัวอย่างเช่นคำขอ GET ไม่ควรสร้างเซสชันบนฐานข้อมูลส่งคืนคุกกี้ด้วย ID เซสชันใหม่หรือไม่ทิ้งสิ่งใด ๆ ไว้บนเซิร์ฟเวอร์ GET verb เป็นเหมือนคำสั่ง SELECT ในเอ็นจิ้นฐานข้อมูล โปรดจำไว้ว่าการตอบสนองต่อคำขอใด ๆ ที่มีคำกริยา GET ควรจะสามารถใช้แคชได้เมื่อถูกร้องขอด้วยพารามิเตอร์เดียวกันเช่นเดียวกับเมื่อคุณร้องขอเว็บเพจแบบคงที่


จุดที่ 3: วิธีคืนข้อความและรหัสข้อผิดพลาด

พิจารณารหัสสถานะ 4xx หรือ 5xx HTTP เป็นหมวดหมู่ข้อผิดพลาด คุณสามารถอธิบายรายละเอียดข้อผิดพลาดในร่างกายได้

ไม่สามารถเชื่อมต่อกับฐานข้อมูล: / เข้าสู่ระบบฐานข้อมูลไม่ถูกต้อง : โดยทั่วไปคุณควรใช้ข้อผิดพลาด 500 ข้อผิดพลาดประเภทนี้ นี่เป็นข้อผิดพลาดฝั่งเซิร์ฟเวอร์ ลูกค้าไม่ได้ทำอะไรผิด 500 ข้อผิดพลาดโดยทั่วไปถือว่า "ลองใหม่" เช่นลูกค้าสามารถลองคำขอที่แน่นอนซ้ำกันได้และคาดว่าจะประสบความสำเร็จเมื่อปัญหาของเซิร์ฟเวอร์ได้รับการแก้ไข ระบุรายละเอียดในร่างกายเพื่อให้ลูกค้าสามารถให้บริบทกับเราได้

ข้อผิดพลาดประเภทอื่นจะเป็นตระกูล 4xx ซึ่งโดยทั่วไประบุว่าลูกค้าทำอะไรผิดพลาด โดยเฉพาะอย่างยิ่งข้อผิดพลาดประเภทนี้โดยปกติจะระบุให้กับลูกค้าว่าไม่จำเป็นต้องลองใหม่ตามที่เป็นอยู่เพราะจะยังคงล้มเหลวอย่างถาวร เช่นลูกค้าต้องการเปลี่ยนแปลงบางสิ่งก่อนที่จะลองคำขอนี้อีกครั้ง ตัวอย่างเช่นข้อผิดพลาด "ไม่พบทรัพยากร" (HTTP 404) หรือ "คำขอผิดรูปแบบ" (HTTP 400) จะอยู่ในหมวดหมู่นี้


จุดที่ 4: วิธีการตรวจสอบความถูกต้อง

ดังที่กล่าวไว้ในจุดที่ 1 แทนการรับรองความถูกต้องของผู้ใช้คุณอาจต้องการคิดเกี่ยวกับการสร้างเซสชัน คุณจะถูกส่งคืน "รหัสเซสชัน" ใหม่พร้อมกับรหัสสถานะ HTTP ที่เหมาะสม (200: การเข้าถึงที่ได้รับหรือ 403: การเข้าถึงถูกปฏิเสธ)

จากนั้นคุณจะถามเซิร์ฟเวอร์ RESTful ของคุณ: "คุณสามารถรับทรัพยากรสำหรับรหัสเซสชันนี้ได้หรือไม่"

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


6
ดีมาก แต่การที่คุณPUTเปลี่ยนรหัสผ่านอาจไม่ถูกต้อง PUTต้องการทรัพยากรทั้งหมดดังนั้นคุณต้องส่งแอตทริบิวต์ผู้ใช้ทั้งหมดเพื่อให้สอดคล้องกับ HTTP (และด้วย HATEOAS REST) แต่เพียงแค่เปลี่ยนรหัสผ่านควรใช้หรือPATCH POST
Lawrence Dol

1
ฉันคิดว่าโพสต์นี้จะสมบูรณ์แบบถ้าคุณขยายเพิ่มเติมเกี่ยวกับสิ่งที่ "โพสต์: ถือว่าสมาชิกที่อยู่ในชุดเป็นของตัวเองและสร้างผู้ใต้บังคับบัญชาใหม่ของมัน" วิธี - ฉันพบความหมายของ Googling - เป็นข้อยกเว้นสำหรับคำตอบที่ดีของคุณ
Martin Konecny

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

1
"สิ่งนี้ขัดกับหลักการ REST ที่สำคัญมาก: การใช้กริยา HTTP ที่ถูกต้องการร้องขอ GET ใด ๆ ไม่ควรมีผลข้างเคียงใด ๆ " - จะทำอย่างไรถ้าคุณต้องการรักษาจำนวนการเข้าชมสำหรับทรัพยากร
bobbyalex

1
บทความนี้ควรตอบคำถามของคุณ saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices
java_geek

79

เพียงแค่คุณกำลังทำสิ่งนี้ย้อนหลังอย่างสมบูรณ์

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

เพื่ออ้างอิงRoy Fielding

REST API ควรใช้ความพยายามเกือบทั้งหมดในการกำหนดประเภทสื่อที่ใช้สำหรับการแสดงทรัพยากรและการขับเคลื่อนสถานะของแอปพลิเคชันหรือในการกำหนดชื่อความสัมพันธ์เพิ่มเติมและ / หรือการเปิดใช้งานมาร์คอัพแบบไฮเปอร์เท็กซ์สำหรับประเภทสื่อมาตรฐานที่มีอยู่ ความพยายามใด ๆ ที่ใช้อธิบายถึงวิธีการที่จะใช้กับสิ่งที่ URIs สนใจควรกำหนดไว้อย่างสมบูรณ์ภายในขอบเขตของกฎการประมวลผลสำหรับประเภทสื่อ [ความล้มเหลวที่นี่หมายถึงว่าข้อมูลนอกวงกำลังผลักดันการมีปฏิสัมพันธ์แทนไฮเปอร์เท็กซ์]

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

พูดตามตรงหลายคนเห็น URIs มากมายและ GETs และ PUT และ POST และคิดว่า REST นั้นง่าย REST ไม่ใช่เรื่องง่าย RPC ผ่าน HTTP เป็นเรื่องง่ายการย้าย blobs ของข้อมูลไปมาพร็อกซีผ่าน HTTP payload เป็นเรื่องง่าย อย่างไรก็ตาม REST ไปได้มากกว่านั้น REST เป็นผู้ไม่เชื่อเรื่องโปรโตคอล HTTP เป็นที่นิยมมากและเหมาะสำหรับระบบ REST

ส่วนที่เหลืออยู่ในประเภทสื่อคำจำกัดความของพวกเขาและวิธีการที่แอพลิเคชันไดรฟ์การกระทำที่มีให้กับทรัพยากรเหล่านั้นผ่านทางไฮเปอร์เท็กซ์ (ลิงค์ได้อย่างมีประสิทธิภาพ)

มีมุมมองที่แตกต่างกันเกี่ยวกับประเภทสื่อในระบบ REST บางคนชอบ payloads เฉพาะแอปพลิเคชันในขณะที่คนอื่นชอบยกระดับประเภทสื่อที่มีอยู่ในบทบาทที่เหมาะสมสำหรับแอปพลิเคชัน ตัวอย่างเช่นในแง่หนึ่งคุณมี XML schema เฉพาะที่ออกแบบมาให้เหมาะกับแอปพลิเคชันของคุณกับการใช้ XHTML เพื่อเป็นตัวแทนของคุณอาจผ่านไมโครฟอร์แมตและกลไกอื่น ๆ

ฉันคิดว่าทั้งสองแนวทางมีที่ของพวกเขา XHTML ทำงานได้ดีมากในสถานการณ์ที่ซ้อนทับทั้งเว็บที่ขับเคลื่อนด้วยมนุษย์และเว็บที่ขับเคลื่อนด้วยเครื่องจักรในขณะที่ประเภทข้อมูลในอดีตที่เฉพาะเจาะจงมากขึ้นฉันรู้สึกดีขึ้น ฉันพบว่ารูปแบบสินค้าในระดับสูงสามารถทำให้การเจรจาต่อรองเนื้อหาทำได้ยาก "application / xml + yourresource" มีความเฉพาะเจาะจงมากกว่าประเภทสื่อมากกว่า "application / xhtml + xml" เนื่องจากหลังสามารถนำไปใช้กับ payload จำนวนมากซึ่งอาจหรืออาจไม่ใช่สิ่งที่ไคลเอ็นต์เครื่องสนใจจริงๆหรือไม่สามารถทำได้ ตรวจสอบโดยไม่ต้องวิปัสสนา

อย่างไรก็ตาม XHTML ทำงานได้ดีมาก (ชัด) ในเว็บของมนุษย์ที่เว็บเบราว์เซอร์และการแสดงผลมีความสำคัญมาก

ใบสมัครของคุณจะแนะนำคุณในการตัดสินใจประเภทนั้น

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

จำได้ว่าการเป็นตัวแทนของทรัพยากรในระบบไฮเปอร์เท็กซ์รวมทั้งการแสดงทรัพยากรจริงพร้อมกับการเปลี่ยนสถานะที่มีให้กับทรัพยากร พิจารณาแต่ละโหนดของทรัพยากรในกราฟโดยมีลิงก์เป็นบรรทัดที่ออกจากโหนดนั้นไปยังสถานะอื่น ลิงค์เหล่านี้แจ้งลูกค้าไม่เพียง แต่สิ่งที่สามารถทำได้ แต่สิ่งที่จำเป็นสำหรับพวกเขาที่จะทำ (เป็นลิงค์ที่ดีรวม URI และประเภทสื่อที่จำเป็น)

ตัวอย่างเช่นคุณอาจมี:

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

เอกสารของคุณจะพูดถึงฟิลด์ rel ที่ชื่อ "users" และประเภทสื่อของ "application / xml + youruser"

ลิงก์เหล่านี้อาจดูเหมือนซ้ำซ้อนพวกเขาทั้งหมดกำลังพูดคุยกับ URI เดียวกันค่อนข้างมาก แต่พวกเขาไม่ได้

นี่เป็นเพราะความสัมพันธ์ "ผู้ใช้" ลิงก์นั้นกำลังพูดถึงการเก็บรวบรวมผู้ใช้และคุณสามารถใช้อินเตอร์เฟสแบบอินเทอร์เฟซเพื่อทำงานกับคอลเลกชัน (GET เพื่อดึงข้อมูลทั้งหมดของพวกเขาลบเพื่อลบทั้งหมด ฯลฯ )

หากคุณโพสต์ไปที่ URL นี้คุณจะต้องผ่านเอกสาร "application / xml + usercollection" ซึ่งอาจจะมีเพียงอินสแตนซ์ผู้ใช้เดียวภายในเอกสารเพื่อให้คุณสามารถเพิ่มผู้ใช้หรืออาจเพิ่มหลายรายการใน ครั้งหนึ่ง บางทีเอกสารของคุณจะแนะนำว่าคุณสามารถส่งผู้ใช้ประเภทเดียวได้แทนที่จะเป็นผู้รวบรวม

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

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

ลูกค้าจำเป็นต้องรู้วิธีจัดการและตีความประเภทสื่อ แต่ไม่จำเป็นต้องสนใจว่าจะไปที่ใด

ลิงก์ทั้งสองนี้มีความหมายเหมือนกันในสายตาลูกค้า:

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

ดังนั้นเน้นทรัพยากรของคุณ มุ่งเน้นไปที่การเปลี่ยนสถานะในแอปพลิเคชันและวิธีการที่ทำได้ดีที่สุด


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

30

อีกครั้ง 1 : ดูดีจนถึงขณะนี้ อย่าลืมส่งคืน URI ของผู้ใช้ที่สร้างขึ้นใหม่ในส่วนหัว "ตำแหน่ง:" ซึ่งเป็นส่วนหนึ่งของการตอบสนองต่อ POST พร้อมกับรหัสสถานะ "201 สร้างแล้ว"

ใหม่ 2: การเปิดใช้งานผ่าน GET เป็นความคิดที่ไม่ดีและการรวมคำกริยาใน URI นั้นเป็นกลิ่นของการออกแบบ คุณอาจต้องการพิจารณาส่งคืนแบบฟอร์มใน GET ในเว็บแอปนี้จะเป็นรูปแบบ HTML พร้อมปุ่มส่ง ในกรณีที่ใช้ API คุณอาจต้องการส่งคืนการแสดงที่มี URI ถึง PUT เพื่อเปิดใช้งานบัญชี แน่นอนคุณสามารถรวม URI นี้ในการตอบสนองต่อ POST ถึง / ผู้ใช้ด้วย การใช้ PUT จะทำให้แน่ใจได้ว่าคำขอของคุณนั้นเป็น idempotent นั่นคือสามารถส่งได้อย่างปลอดภัยอีกครั้งหากลูกค้าไม่แน่ใจเกี่ยวกับความสำเร็จ โดยทั่วไปให้นึกถึงแหล่งข้อมูลที่คุณสามารถเปลี่ยนคำกริยาของคุณให้เป็น (คำว่า "คำนามคำกริยา") ถามตัวคุณเองว่าวิธีการเฉพาะของคุณนั้นสอดคล้องกับวิธีใดมากที่สุด เช่น change_password -> PUT; ปิดใช้งาน -> อาจจะลบ add_credit -> อาจเป็น POST หรือ PUT

re 3.อย่าคิดค้นรหัสสถานะใหม่เว้นแต่ว่าคุณเชื่อว่าเป็นรหัสทั่วไปพวกเขาควรได้รับการรับรองมาตรฐานทั่วโลก พยายามอย่างหนักเพื่อใช้รหัสสถานะที่เหมาะสมที่สุดที่มีอยู่ (อ่านเกี่ยวกับรหัสทั้งหมดใน RFC 2616) รวมข้อมูลเพิ่มเติมในเนื้อหาการตอบกลับ หากคุณแน่ใจจริงๆว่าคุณต้องการประดิษฐ์รหัสสถานะใหม่ลองคิดใหม่อีกครั้ง หากคุณยังเชื่อเช่นนั้นโปรดเลือกหมวดหมู่ที่ถูกต้อง (1xx -> ตกลง, 2xx -> ข้อมูล, 3xx -> การเปลี่ยนเส้นทาง; 4xx-> ข้อผิดพลาดไคลเอนต์ 5xx -> เซิร์ฟเวอร์ผิดพลาด) ฉันพูดถึงการประดิษฐ์รหัสสถานะใหม่เป็นความคิดที่ไม่ดีหรือไม่?

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


คุณช่วยอธิบายได้ไหมว่าทำไมไม่ใส่คีย์ API ใน URL เป็นเพราะพวกเขามองเห็นได้ในบันทึกพร็อกซี่? จะเกิดอะไรขึ้นถ้าปุ่มต่าง ๆ เป็นแบบชั่วคราวตามเวลา จะทำอย่างไรถ้าใช้ HTTPS
MikeSchinkel

4
นอกเหนือจากการละเมิดวิญญาณ (URIs ควรระบุสิ่งต่าง ๆ ) สิ่งสำคัญที่สุดคือการทำลายแคช
Stefan Tilkov

22

1.คุณมีความคิดที่ถูกต้องเกี่ยวกับวิธีการออกแบบทรัพยากรของคุณ IMHO ฉันจะไม่เปลี่ยนแปลงอะไร

2.แทนที่จะพยายามขยาย HTTP ด้วยคำกริยาให้มากขึ้นลองพิจารณาว่าคำกริยาที่เสนอของคุณสามารถลดลงได้อย่างไรในแง่ของวิธีการและทรัพยากร HTTP พื้นฐาน ตัวอย่างเช่นแทนที่จะเป็นactivate_loginคำกริยาคุณสามารถตั้งค่าทรัพยากรเช่น: /api/users/1/login/activeซึ่งเป็นบูลีนแบบง่าย หากต้องการเปิดใช้งานการเข้าสู่ระบบเพียงPUTเอกสารที่ระบุว่า 'จริง' หรือ 1 หรืออะไรก็ตาม หากต้องการปิดใช้งานPUTเอกสารที่นั่นว่างเปล่าหรือบอกว่า 0 หรือเท็จ

ในทำนองเดียวกันการเปลี่ยนแปลงหรือรหัสผ่านชุดเพียงแค่ทำเพื่อPUT/api/users/1/password

เมื่อใดก็ตามที่คุณจะต้องเพิ่มบางสิ่งบางอย่าง (เช่นเครดิต) คิดในแง่ของPOSTs ตัวอย่างเช่นคุณสามารถPOSTเพิ่มทรัพยากรเช่นเดียว/api/users/1/creditsกับเนื้อหาที่มีจำนวนเครดิตที่จะเพิ่ม PUTทรัพยากรเดียวกันสามารถนำมาใช้ในการเขียนทับค่ามากกว่าเพิ่ม A ที่POSTมีตัวเลขติดลบในร่างกายจะลบและอื่น ๆ

3.ฉันขอแนะนำอย่างยิ่งให้ไม่ขยายรหัสสถานะ HTTP พื้นฐาน หากคุณไม่พบสิ่งที่ตรงกับสถานการณ์ของคุณให้เลือกอันที่ใกล้เคียงที่สุดแล้วใส่รายละเอียดข้อผิดพลาดในส่วนการตอบกลับ นอกจากนี้โปรดจำไว้ว่าส่วนหัว HTTP นั้นสามารถขยายได้ แอปพลิเคชันของคุณสามารถกำหนดส่วนหัวที่กำหนดเองทั้งหมดที่คุณต้องการ หนึ่งโปรแกรมที่ผมทำงานอยู่เช่นอาจกลับมา404 Not Foundภายใต้สถานการณ์ที่หลาย ๆ แทนที่จะทำให้ลูกค้าแยกวิเคราะห์เนื้อหาการตอบสนองด้วยเหตุผลเราเพิ่งเพิ่มส่วนหัวใหม่X-Status-Extendedซึ่งมีส่วนขยายรหัสสถานะที่เป็นกรรมสิทธิ์ของเรา ดังนั้นคุณอาจเห็นคำตอบเช่น:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

ด้วยวิธีนี้ไคลเอนต์ HTTP เช่นเว็บเบราว์เซอร์จะยังคงรู้ว่าต้องทำอย่างไรกับรหัส 404 ปกติและไคลเอนต์ HTTP ที่ซับซ้อนยิ่งขึ้นสามารถเลือกดูX-Status-Extendedหัวข้อสำหรับข้อมูลที่เฉพาะเจาะจงมากขึ้น

4.สำหรับการรับรองความถูกต้องผมขอแนะนำให้ใช้การตรวจสอบ HTTP ถ้าคุณสามารถ แต่ IMHO ไม่มีอะไรผิดปกติในการใช้การรับรองความถูกต้องแบบอิงคุกกี้หากง่ายกว่าสำหรับคุณ


4
แนวคิดที่เรียบร้อยในการใช้ทรัพยากร "ขยาย" เพื่อทำสิ่งต่างๆกับส่วนเล็ก ๆ ของทรัพยากรที่มีขนาดใหญ่ขึ้น
womble

1
คุกกี้ใช้งานได้ใน HTTP / REST แต่เซิร์ฟเวอร์ไม่ควรจัดเก็บคุกกี้เป็นสถานะ (ดังนั้นจึงไม่ใช่เซสชัน) คุกกี้สามารถจัดเก็บค่าเช่น HMAC ซึ่งสามารถถอดแยกชิ้นส่วนได้โดยไม่ต้องมองหาที่อื่น
Bruce Alderson

14

ข้อมูลพื้นฐานเกี่ยวกับส่วนที่เหลือ

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

ดังนั้นจึงมีสัญญาระหว่างไคลเอนต์ REST และบริการ REST หากคุณใช้ HTTP เป็นโปรโตคอลพื้นฐานมาตรฐานต่อไปนี้เป็นส่วนหนึ่งของสัญญา:

  • HTTP 1.1
    • นิยามวิธีการ
    • นิยามรหัสสถานะ
    • ส่วนหัวควบคุมแคช
    • ส่วนหัวยอมรับและเนื้อหา
    • ส่วนหัวรับรองความถูกต้อง
  • IRI (utf8 URI )
  • ร่างกาย (เลือกหนึ่งรายการ)
    • แอปพลิเคชันที่ลงทะเบียนประเภท MIME เฉพาะเช่นเขาวงกต + xml
    • ประเภท MIME เฉพาะของผู้ขายเช่นvnd.github + json
    • ประเภท MIME ทั่วไปกับ
      • แอปพลิเคชันเฉพาะ RDF คำศัพท์เช่นld + json & hydra , schema.org
      • โปรไฟล์เฉพาะแอปพลิเคชันเช่นพารามิเตอร์Hal + json & ลิงก์โปรไฟล์ (ฉันเดา)
  • เชื่อมโยงหลายมิติ
    • สิ่งที่ควรมี (เลือกหนึ่งรายการ)
      • ส่งในส่วนหัวของลิงค์
      • กำลังส่งการตอบกลับสื่อหลายมิติเช่น html, atom + xml, hal + json, ld + json & hydra ฯลฯ ...
    • อรรถศาสตร์
      • ใช้ความสัมพันธ์ลิงค์ IANA และอาจเชื่อมโยงความสัมพันธ์ที่กำหนดเอง
      • ใช้คำศัพท์ RDF เฉพาะแอปพลิเคชัน

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

เพื่อตอบคำถามคุณ

  1. ใช่มันสามารถ

    เพียงแค่พูดถึงลูกค้าไม่สนใจเกี่ยวกับโครงสร้าง IRI พวกเขาสนใจเกี่ยวกับความหมายเพราะพวกเขาติดตามการเชื่อมโยงที่มีความสัมพันธ์เชื่อมโยงหรือแอตทริบิวต์ที่เชื่อมโยงข้อมูล (RDF)

    สิ่งเดียวที่สำคัญเกี่ยวกับ IRIs ที่ IRI เดียวต้องระบุเพียงทรัพยากรเดียว ได้รับอนุญาตให้ใช้ทรัพยากรเดียวเช่นผู้ใช้มี IRIs ที่แตกต่างกันมากมาย

    มันสวยเรียบง่ายว่าทำไมเราใช้ IRIS ดีเช่น/users/123/password; มันง่ายกว่ามากในการเขียนตรรกะการเราติ้งบนเซิร์ฟเวอร์เมื่อคุณเข้าใจ IRI เพียงแค่อ่านมัน

  2. คุณมีคำกริยาเพิ่มเติมเช่น PUT, PATCH, OPTIONS และอื่น ๆ อีกมากมาย แต่คุณไม่ต้องการมากกว่านั้น ... แทนที่จะเพิ่มกริยาใหม่คุณต้องเรียนรู้วิธีเพิ่มทรัพยากรใหม่

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (การเข้าสู่ระบบไม่สมเหตุสมผลจากมุมมอง REST เนื่องจากข้อ จำกัด ด้านสถานะ)

  3. ผู้ใช้ของคุณไม่สนใจว่าเหตุใดจึงเกิดปัญหา พวกเขาต้องการทราบว่ามีความสำเร็จหรือข้อผิดพลาดและอาจเป็นข้อความแสดงข้อผิดพลาดที่พวกเขาสามารถเข้าใจได้ตัวอย่างเช่น: "ขออภัย แต่เราไม่สามารถบันทึกโพสต์ของคุณ" ฯลฯ

    ส่วนหัวสถานะ HTTP เป็นส่วนหัวมาตรฐานของคุณ ทุกอย่างควรอยู่ในร่างกายฉันคิดว่า ส่วนหัวเดียวไม่เพียงพอที่จะอธิบายเช่นข้อความแสดงข้อผิดพลาดหลายภาษาโดยละเอียด

  4. ข้อ จำกัด ที่ไร้รัฐ (พร้อมกับแคชและข้อ จำกัด ของระบบแบบเลเยอร์) ทำให้แน่ใจได้ว่าบริการขยายตัวได้ดี แน่นอนว่าคุณไม่ต้องการรักษาเซสชันหลายล้านรายการบนเซิร์ฟเวอร์เมื่อคุณสามารถทำเช่นเดียวกันกับลูกค้า ...

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

วรรณคดีที่เกี่ยวข้อง


11

สำหรับตัวอย่างที่คุณระบุฉันจะใช้สิ่งต่อไปนี้:

activate_login

POST /users/1/activation

deactivate_login

DELETE /users/1/activation

เปลี่ยนรหัสผ่าน

PUT /passwords (สิ่งนี้ถือว่าผู้ใช้ผ่านการพิสูจน์ตัวตนแล้ว)

add_credit

POST /credits (สิ่งนี้ถือว่าผู้ใช้ผ่านการพิสูจน์ตัวตนแล้ว)

สำหรับข้อผิดพลาดคุณจะส่งคืนข้อผิดพลาดในเนื้อหาในรูปแบบที่คุณได้รับคำขอดังนั้นหากคุณได้รับ:

DELETE /users/1.xml

คุณต้องการส่งคำตอบกลับเป็น XML สิ่งเดียวกันจะเป็นจริงสำหรับ JSON ฯลฯ ...

สำหรับการรับรองความถูกต้องคุณควรใช้การรับรองความถูกต้องของ http


1
ฉันจะไม่ใช้createเป็นส่วนหนึ่งของ URI (โปรดจำไว้ว่า URIs ควรเป็นคำนามและเมธอด HTTP ควรเป็นคำกริยาที่ใช้กับคำนามเหล่านั้น) แต่ฉันจะมีทรัพยากร/users/1/activeที่สามารถเป็นบูลีนแบบง่ายและสามารถ กำหนดโดย PUTting 1 หรือ 0 ไปยังทรัพยากรที่
Friedo

คุณพูดถูกฉันเอาออก / สร้าง มันควรจะเป็นโพสต์ไปยังทรัพยากรซิงเกิล
jonnii

3
ฉันจะไม่ใช้activationใน URI /users/1/activationใดเว้นแต่ว่าคุณจะจัดการและการจัดการทรัพยากรโดยใช้ชื่อของ GET ทำอะไรได้บ้าง? PUT ทำอะไร ฉันรู้สึกว่าคุณกำลังยืนยัน URI นอกจากนี้ยังเป็นสำหรับชนิดเนื้อหาการเจรจาต่อรองที่เป็นก็มักจะดีที่สุดออกจาก URI Acceptและแทรกเข้าไปในหัวเหมือน
Cheeso

6
  1. ใช้การโพสต์เมื่อคุณไม่ทราบว่าจะมีหน้าตาเป็นอย่างไรทรัพยากร URI ใหม่ (คุณสร้างผู้ใช้ใหม่แอปพลิเคชันจะกำหนดผู้ใช้ใหม่เป็น id), PUT สำหรับการอัปเดตหรือสร้างทรัพยากรที่คุณรู้ว่าจะแสดงอย่างไร : PUT /myfiles/thisismynewfile.txt)
  2. คืนคำอธิบายข้อผิดพลาดในเนื้อหาของข้อความ
  3. คุณสามารถใช้การพิสูจน์ตัวตน HTTP (ถ้ามี) บริการบนเว็บควรเป็นสเตเทล

5

ฉันขอแนะนำ (เป็นครั้งแรก) ที่PUTควรจะใช้สำหรับการปรับปรุงเอนทิตีที่มีอยู่ POSTควรใช้สำหรับการสร้างใหม่ กล่าวคือ

/api/users     when called with PUT, creates user record

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


อาจมีบางคนคิดว่านี่ไม่ใช่คำตอบสำหรับคำถามของเขาจริงๆ
lubos hasko

6
การใช้ PUT กับ POST ของฉันสำหรับการสร้างเอนทิตีใหม่คือการใช้ PUT เมื่อผู้เรียกควบคุมชื่อทรัพยากรดังนั้นคุณสามารถ PUT ไปยังทรัพยากรที่แน่นอนและ POST เมื่อผู้รับสายควบคุมชื่อทรัพยากรใหม่ (เช่นในตัวอย่างที่นี่)
SteveD

5

อย่างละเอียด แต่คัดลอกมาจากข้อกำหนดวิธีการ HTTP 1.1 ที่http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9.3 GET

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

ซีแมนทิกส์ของเมธอด GET จะเปลี่ยนเป็น "เงื่อนไขแบบรับ" หากข้อความคำร้องขอมีฟิลด์ If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match หรือ If-Range เมธอด GET แบบมีเงื่อนไขร้องขอให้โอนเอนทิตีภายใต้สถานการณ์ที่อธิบายโดยฟิลด์ส่วนหัวที่มีเงื่อนไข วิธี GET แบบมีเงื่อนไขมีจุดประสงค์เพื่อลดการใช้เครือข่ายที่ไม่จำเป็นโดยอนุญาตให้รีเฟรชเอนทิตีที่แคชไว้โดยไม่ต้องร้องขอหลายครั้งหรือถ่ายโอนข้อมูลที่มีอยู่แล้วโดยไคลเอ็นต์

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

การตอบสนองต่อการร้องขอ GET นั้นสามารถแคชได้ถ้าหากเป็นไปตามข้อกำหนดสำหรับการแคช HTTP ที่อธิบายไว้ในส่วนที่ 13

ดูส่วนที่ 15.1.3 สำหรับข้อควรพิจารณาด้านความปลอดภัยเมื่อใช้กับแบบฟอร์ม

9.5 โพสต์

เมธอด POST ใช้เพื่อร้องขอให้เซิร์ฟเวอร์ต้นทางยอมรับเอนทิตีที่อยู่ในคำขอเป็นผู้ใต้บังคับบัญชาใหม่ของทรัพยากรที่ระบุโดย Request-URI ใน Request-Line POST ได้รับการออกแบบมาเพื่อให้วิธีการแบบเดียวกันครอบคลุมฟังก์ชั่นต่อไปนี้:

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

ฟังก์ชั่นที่เกิดขึ้นจริงดำเนินการโดยวิธีการ POST จะถูกกำหนดโดยเซิร์ฟเวอร์และมักจะขึ้นอยู่กับ Request-URI เอนทิตีที่ถูกโพสต์นั้นเป็นสังกัดอยู่ใน URI นั้นในลักษณะเดียวกับที่ไฟล์นั้นถูกส่งไปยังไดเรคทอรี่ที่มีอยู่บทความข่าวจะถูกส่งไปยังกลุ่มข่าวสารที่โพสต์ไว้หรือบันทึกเป็นสังกัด

การกระทำที่ดำเนินการโดยวิธี POST อาจไม่ส่งผลให้เกิดทรัพยากรที่สามารถระบุได้โดย URI ในกรณีนี้ 200 (OK) หรือ 204 (ไม่มีเนื้อหา) เป็นสถานะการตอบสนองที่เหมาะสมขึ้นอยู่กับว่าการตอบสนองนั้นมีเอนทิตีที่อธิบายผลลัพธ์หรือไม่

หากมีการสร้างทรัพยากรบนเซิร์ฟเวอร์ต้นทางการตอบสนองควรเป็น 201 (สร้างขึ้น) และมีเอนทิตีที่อธิบายสถานะของคำขอและอ้างอิงถึงทรัพยากรใหม่และส่วนหัวตำแหน่งที่ตั้ง (ดูหัวข้อ 14.30)

การตอบสนองต่อวิธีนี้จะไม่สามารถแคชได้เว้นแต่ว่าการตอบกลับจะรวมถึงการควบคุมแคชหรือฟิลด์ส่วนหัวที่หมดอายุ อย่างไรก็ตามการตอบสนอง 303 (ดูอื่น ๆ ) สามารถนำมาใช้เพื่อกำหนดตัวแทนผู้ใช้เพื่อดึงทรัพยากรที่แคชได้

คำขอ POST ต้องปฏิบัติตามข้อกำหนดการส่งข้อความที่กำหนดไว้ในส่วนที่ 8.2

ดูหัวข้อ 15.1.3 สำหรับข้อควรพิจารณาด้านความปลอดภัย

9.6 PUT

วิธี PUT ร้องขอให้เก็บเอนทิตีที่ถูกล้อมไว้ภายใต้ Request-URI ที่ให้มา หาก Request-URI อ้างถึงทรัพยากรที่มีอยู่แล้วนิติบุคคลที่ปิดอยู่ควรได้รับการพิจารณาว่าเป็นเวอร์ชันดัดแปลงขององค์กรที่อยู่ในเซิร์ฟเวอร์ต้นทาง หาก Request-URI ไม่ได้ชี้ไปที่ทรัพยากรที่มีอยู่และ URI นั้นสามารถกำหนดเป็นทรัพยากรใหม่ได้โดยตัวแทนผู้ใช้ที่ร้องขอเซิร์ฟเวอร์ต้นทางสามารถสร้างทรัพยากรด้วย URI นั้น หากมีการสร้างทรัพยากรใหม่เซิร์ฟเวอร์ต้นทางต้องแจ้งตัวแทนผู้ใช้ผ่านการตอบกลับ 201 (สร้าง) หากมีการแก้ไขทรัพยากรที่มีอยู่ให้ส่งรหัสตอบกลับ 200 (OK) หรือ 204 (ไม่มีเนื้อหา) เพื่อบ่งชี้ว่าการร้องขอสำเร็จ หากไม่สามารถสร้างหรือแก้ไขทรัพยากรด้วย Request-URI การตอบสนองข้อผิดพลาดที่เหมาะสมควรได้รับที่สะท้อนถึงลักษณะของปัญหา ผู้รับเอนทิตีต้องไม่เพิกเฉยต่อส่วนหัวของ Content- * (เช่น Content-Range) ที่ไม่เข้าใจหรือนำไปใช้และต้องส่งคืนการตอบสนอง 501 (ไม่นำไปใช้) ในกรณีดังกล่าว

หากการร้องขอผ่านแคชและ Request-URI ระบุเอนทิตีแคชในปัจจุบันอย่างน้อยหนึ่งรายการรายการเหล่านั้นควรถูกใช้เป็นค้าง การตอบสนองต่อวิธีนี้ไม่สามารถแคชได้

ความแตกต่างพื้นฐานระหว่างคำขอ POST และ PUT สะท้อนให้เห็นในความหมายที่แตกต่างกันของ Request-URI URI ในคำขอ POST ระบุทรัพยากรที่จะจัดการกับเอนทิตีที่ปิดล้อม ทรัพยากรนั้นอาจเป็นกระบวนการยอมรับข้อมูลเกตเวย์ไปยังโปรโตคอลอื่นหรือเอนทิตีแยกต่างหากที่ยอมรับคำอธิบายประกอบ ในทางตรงกันข้าม URI ในคำขอ PUT จะระบุเอนทิตีที่แนบมากับคำขอ - ตัวแทนผู้ใช้รู้ว่า URI มีจุดประสงค์อะไรและเซิร์ฟเวอร์ต้องไม่พยายามใช้คำขอกับทรัพยากรอื่น ๆ หากเซิร์ฟเวอร์ต้องการให้มีการนำคำขอไปใช้กับ URI อื่น

มันต้องส่งการตอบสนอง 301 (ย้ายอย่างถาวร) ตัวแทนผู้ใช้อาจตัดสินใจเองว่าจะเปลี่ยนเส้นทางคำขอหรือไม่

อาจระบุทรัพยากรเดียวโดย URI ที่แตกต่างกันจำนวนมาก ตัวอย่างเช่นบทความอาจมี URI สำหรับระบุ "รุ่นปัจจุบัน" ซึ่งแยกจาก URI ที่ระบุแต่ละรุ่น ในกรณีนี้คำขอ PUT บน URI ทั่วไปอาจส่งผลให้มีการระบุ URI อื่น ๆ อีกหลายรายการโดยเซิร์ฟเวอร์ต้นทาง

HTTP / 1.1 ไม่ได้กำหนดว่าวิธีการ PUT มีผลต่อสถานะของเซิร์ฟเวอร์ต้นทางอย่างไร

คำขอ PUT ต้องปฏิบัติตามข้อกำหนดการส่งข้อความที่กำหนดไว้ในส่วนที่ 8.2

เว้นแต่จะระบุไว้เป็นอย่างอื่นสำหรับส่วนหัวเอนทิตีเฉพาะเอนทิตีส่วนหัวในคำขอ PUT ควรใช้กับทรัพยากรที่สร้างหรือแก้ไขโดย PUT

9.7 DELETE

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

การตอบสนองที่ประสบความสำเร็จควรเป็น 200 (OK) หากการตอบสนองนั้นรวมถึงเอนทิตีที่อธิบายสถานะ 202 (ยอมรับแล้ว) หากการกระทำนั้นยังไม่ได้มีการประกาศใช้หรือ 204 (ไม่มีเนื้อหา) หากการกระทำนั้นมีการตราขึ้นแล้ว นิติบุคคล

หากการร้องขอผ่านแคชและ Request-URI ระบุเอนทิตีแคชในปัจจุบันอย่างน้อยหนึ่งรายการรายการเหล่านั้นควรถูกใช้เป็นค้าง การตอบสนองต่อวิธีนี้ไม่สามารถแคชได้


2

เกี่ยวกับรหัสส่งคืน REST: เป็นเรื่องผิดที่จะผสมรหัสโปรโตคอล HTTP และผลลัพธ์ REST

อย่างไรก็ตามฉันเห็นการใช้งานหลายอย่างผสมกันและนักพัฒนาหลายคนอาจไม่เห็นด้วยกับฉัน

รหัสส่งคืน HTTP เกี่ยวข้องกับHTTP Requestตัวเอง การเรียกใช้ REST เสร็จสิ้นโดยใช้การร้องขอ Hypertext Transfer Protocol และทำงานในระดับที่ต่ำกว่าวิธี REST ที่เรียกใช้ REST เป็นแนวคิด / วิธีการและผลลัพธ์เป็นผลลัพธ์ทางธุรกิจ / ตรรกะในขณะที่โค้ดผลลัพธ์ HTTP คือการส่งผ่าน

ตัวอย่างเช่นการส่งคืน "404 ไม่พบ" เมื่อคุณโทร / ผู้ใช้ / สับสนเนื่องจากอาจหมายถึง:

  • URI ผิด (HTTP)
  • ไม่พบผู้ใช้ (REST)

"403 ถูกห้าม / ปฏิเสธการเข้าถึง" อาจหมายถึง:

  • ต้องได้รับอนุญาตพิเศษ เบราว์เซอร์สามารถจัดการได้โดยขอให้ผู้ใช้ / รหัสผ่าน (HTTP)
  • สิทธิ์การเข้าถึงไม่ถูกต้องกำหนดค่าบนเซิร์ฟเวอร์ (HTTP)
  • คุณต้องได้รับการรับรองความถูกต้อง (REST)

และรายการอาจดำเนินการต่อโดยมีข้อผิดพลาด '500 เซิร์ฟเวอร์ "(ข้อผิดพลาดโยน Apache / Nginx HTTP หรือข้อผิดพลาดข้อ จำกัด ทางธุรกิจใน REST) ​​หรือข้อผิดพลาด HTTP อื่น ๆ ฯลฯ ...

จากรหัสนั้นยากที่จะเข้าใจว่าอะไรคือสาเหตุของความล้มเหลวความล้มเหลว HTTP (การขนส่ง) หรือความล้มเหลว REST (ตรรกะ)

หากคำขอ HTTP ดำเนินการทางร่างกายสำเร็จแล้วควรส่งคืนรหัส 200 เสมอไม่ว่าจะพบระเบียนหรือไม่ก็ตาม เนื่องจากพบทรัพยากร URI และจัดการโดยเซิร์ฟเวอร์ http ใช่มันอาจส่งคืนชุดที่ว่างเปล่า เป็นไปได้ไหมที่จะได้รับหน้าเว็บเปล่าที่มี 200 ผลลัพธ์เป็น http ใช่มั้ย

แทนที่จะเป็นเช่นนี้คุณอาจส่งคืนรหัส HTTP 200 และเพียงแค่ JSON ด้วยอาร์เรย์ / วัตถุว่างเปล่าหรือใช้แฟล็กผลลัพธ์ / ความสำเร็จบูลเพื่อแจ้งเกี่ยวกับสถานะการทำงานที่ดำเนินการ

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

จากWiki :

ในเดือนกรกฎาคม 2004 กลุ่มผู้ให้บริการโทรคมนาคมของสหราชอาณาจักรกลุ่ม BT ได้ติดตั้งระบบบล็อกเนื้อหา Cleanfeed ซึ่งจะส่งกลับข้อผิดพลาด 404 ไปยังคำขอใด ๆ สำหรับเนื้อหาที่ระบุว่าอาจผิดกฎหมายโดย Internet Watch Foundation ISP อื่น ๆ ส่งคืนข้อผิดพลาด "ต้องห้าม" HTTP 403 ในสถานการณ์เดียวกัน ในประเทศไทยและตูนิเซียมีรายงานการปฏิบัติที่ใช้ข้อผิดพลาดปลอม 404 เพื่อปกปิดการเซ็นเซอร์ ในตูนิเซียที่การเซ็นเซอร์รุนแรงก่อนการปฏิวัติปี 2554 ผู้คนเริ่มตระหนักถึงธรรมชาติของข้อผิดพลาดปลอม 404 และสร้างตัวละครในจินตนาการชื่อ "Ammar 404" ซึ่งเป็นตัวแทนของ "เซ็นเซอร์ที่มองไม่เห็น"

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