http - PUT مقابل POST في REST




(20)

وفقا ل HTTP / 1.1 المواصفات:

تُستخدم طريقة POST لطلب أن يقبل خادم الأصل الكيان الذي تم تضمينه في الطلب كجهة فرعية جديدة من الموارد المحددة بواسطة Request-URI في Request-Line

وبعبارة أخرى ، يتم استخدام POST لإنشاء .

تطلب طريقة PUT أن يتم تخزين الكيان المرفق تحت Request-URI المطلوب. إذا كان Request-URI يشير إلى مورد موجود بالفعل ، فيجب اعتبار الكيان المرفق كإصدار معدل للواحد المقيم على خادم المصدر. إذا لم يكن Request-URI يشير إلى مورد موجود ، وكان URI قادرًا على أن يتم تعريفه كمورد جديد بواسطة وكيل المستخدم المطالب ، يمكن لخادم الأصل إنشاء المورد باستخدام ذلك المعرِّف URI. "

هذا هو ، PUT يستخدم لإنشاء أو تحديث .

لذا ، ما الذي يجب استخدامه لإنشاء مورد؟ أو يحتاج المرء لدعم كلا؟


يمكن لخادم الأصل إنشاء المورد باستخدام URI

لذلك كنت تستخدم POST وربما ، ولكن ليس من الضروري PUT لإنشاء الموارد. ليس عليك دعم كليهما. بالنسبة لي POST هو تماما بما فيه الكفاية. لذلك هو قرار التصميم.

كما ذكر مقولتك ، يمكنك استخدام PUT لإنشاء لا يوجد مورد مخصص لـ IRI ، وتريد إنشاء مورد على أي حال. على سبيل المثال ، PUT /users/123/passwordيستبدل عادة كلمة المرور القديمة بأخرى جديدة ، ولكن يمكنك استخدامها لإنشاء كلمة مرور إذا لم تكن موجودة بالفعل (على سبيل المثال ، من خلال المستخدمين المسجلين حديثًا أو باستعادة المستخدمين المحظورين).


ملخص:

خلق:

يمكن تنفيذ كل من PUT أو POST بالطريقة التالية:

ضع

ينشئ المورد الجديد باستخدام newResourceId كمعرّف ، ضمن / URI الموارد ، أو المجموعة .

PUT /resources/<newResourceId> HTTP/1.1 

بريد

ينشئ موردًا جديدًا ضمن / URI الموارد ، أو المجموعة . عادة يتم إرجاع المعرف من قبل الخادم.

POST /resources HTTP/1.1

تحديث:

يمكن فقط تنفيذ PUT بالطريقة التالية:

ضع

يقوم بتحديث المورد مع existingResourceId كمعرف ، ضمن / URI الموارد ، أو مجموعة .

PUT /resources/<existingResourceId> HTTP/1.1

تفسير:

عند التعامل مع REST و URI بصفة عامة ، لديك عام على اليسار ومحددة على اليمين . عادة ما يطلق على الأدوية اسم المجموعات ويمكن تسمية العناصر الأكثر تحديدًا بالمورد. لاحظ أنه يمكن أن يحتوي المورد على مجموعة .

أمثلة:

<- عام - محدد ->

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

عندما تستخدم POST ، فأنت دائمًا ما تشير إلى مجموعة ، لذلك كلما قلت:

POST /users HTTP/1.1

تقوم بنشر مستخدم جديد إلى مجموعة المستخدمين .

إذا ذهبت وحاولت شيئًا كهذا:

POST /users/john HTTP/1.1

ستعمل ، ولكن بشكل لغوي تقول أنك تريد إضافة مورد إلى مجموعة john ضمن مجموعة المستخدمين .

بمجرد استخدام PUT ، فإنك تشير إلى مورد أو عنصر واحد ، ربما داخل مجموعة . لذلك عندما تقول:

PUT /users/john HTTP/1.1

أنت تخبرك بتحديث الخادم ، أو تنشئ إذا لم يكن موجودًا ، مورد john ضمن مجموعة المستخدمين .

المواصفات:

دعوني أسلط الضوء على بعض الأجزاء المهمة من المواصفات:

بريد

تُستخدم طريقة POST لطلب أن يقبل خادم الأصل الكيان الذي تم تضمينه في الطلب كجهة فرعية جديدة من الموارد المحددة بواسطة طلب-URI في طلب الخط

وبالتالي ، يقوم بإنشاء مورد جديد في مجموعة .

ضع

تطلب طريقة PUT أن يتم تخزين الكيان المرفق تحت عنوان URI المطلوب. إذا كان Request-URI يشير إلى مورد موجود بالفعل ، فيجب اعتبار الكيان المرفق كإصدار معدل للواحد المقيم على خادم المصدر. إذا لم يكن طلب-URI يشير إلى مورد موجود ، وكان URI قادرًا على أن يتم تعريفه كمورد جديد بواسطة وكيل المستخدم المطالب ، يمكن لخادم الأصل إنشاء المورد باستخدام ذلك المعرِّف URI. "

وبالتالي ، إنشاء أو تحديث يستند إلى وجود المورد .

مرجع:


REST هو مفهوم على مستوى عال جدا . في الحقيقة ، إنه لا يذكر HTTP على الإطلاق!

إذا كانت لديك أي شكوك حول كيفية تنفيذ REST في HTTP ، فيمكنك دائمًا إلقاء نظرة على مواصفات بروتوكول Atom Publication Protocol (AtomPub) . AtomPub هو معيار لكتابة RESTful webservices مع HTTP تم تطويره بواسطة العديد من نصوص HTTP و REST ، مع بعض المدخلات من Roy Fielding ، مخترع REST والمخترع المشترك لـ (HTTP) نفسه.

في الواقع ، قد تكون قادرًا على استخدام AtomPub مباشرة. في حين أنها خرجت من مجتمع التدوين ، فإنه لا يقتصر بأي شكل من الأشكال على التدوين: بل هو بروتوكول عام للتفاعل مع مجموعات عشوائية (متداخلة) من الموارد التعسفية عبر HTTP. إذا كان بإمكانك تمثيل تطبيقك كمجموعة متداخلة من الموارد ، فيمكنك استخدام AtomPub فقط وعدم القلق بشأن استخدام PUT أو POST ، وما هي رموز حالة HTTP التي سيتم إرجاعها وكافة هذه التفاصيل.

هذا ما يجب على AtomPub قوله عن إنشاء الموارد (القسم 9.2):

لإضافة أعضاء إلى مجموعة ، يرسل العملاء طلبات POST إلى URI الخاص بالمجموعة.


أود إضافة مشورة "براغماتية". استخدم PUT عندما تعرف "id" الذي يمكن استرداد الكائن الذي تقوم بحفظه. لن يعمل استخدام PUT جيدًا إذا كنت بحاجة إلى ، على سبيل المثال ، إدخال معرف تم إنشاؤه لقاعدة البيانات لك لإجراء عمليات بحث أو تحديثات مستقبلية.

لذلك: لحفظ مستخدم حالي ، أو واحد حيث ينشئ العميل المعرّف وتم التحقق من أن المعرّف فريد من نوعه:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

خلاف ذلك ، استخدم POST لإنشاء الكائن في البداية ، و PUT لتحديث الكائن:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

يمكنك العثور على التأكيدات على شبكة الإنترنت التي تقول

لا هو على حق تماما.

الأفضل هو أن تختار بين PUT و POST على أساس idempotence للعمل.

PUT يعني وضع مورد - تماما استبدال كل ما هو متاح في عنوان URL مع شيء مختلف. بحكم التعريف ، هو PUT هو idempotent. افعل ذلك قدر ما تشاء ، والنتيجة هي نفسها. x=5 هو اكينتيمنتينت. يمكنك وضع مورد ما إذا كان موجودًا من قبل ، أو لا (على سبيل المثال ، لإنشاء ، أو تحديث)!

يقوم POST بتحديث مورد أو إضافة مورد فرعي أو حدوث تغيير. POST ليس idempotent ، بالطريقة التي x++ ليس idempotent.

من خلال هذه الوسيطة ، PUT هي لإنشاء عندما تعرف عنوان URL للشيء الذي ستقوم بإنشائه. يمكن استخدام POST لإنشاء عندما تعرف عنوان URL الخاص بـ "المصنع" أو المدير لفئة الأشياء التي ترغب في إنشائها.

وبالتالي:

POST /expense-report

أو:

PUT  /expense-report/10929

إجابة جديدة (الآن بعد أن فهمت أفضل):

PUT هو مجرد بيان عن المحتوى الذي يجب أن تستخدمه الخدمة ، من الآن فصاعدًا ، لتقديم تمثيل للمورد الذي حدده العميل ؛ POST هو عبارة عن بيان حول المحتوى الذي يجب أن تحتوي عليه الخدمة ، من الآن فصاعدًا ، (من المحتمل أن يكون مكررًا) ولكن يعود إلى الخادم كيفية تحديد هذا المحتوى.

PUT x(إذا xحددت resource ): "استبدل محتوى المورد المحدد بواسطة xالمحتوى الخاص بي."

PUT x(إذا xلم يتم تحديد مورد): "أنشئ موردًا جديدًا يحتوي على المحتوى الخاص بي واستخدمه xلتعريفه."

POST x: "قم بتخزين المحتوى الخاص بي وأعطيني مُعرّفًا يمكنني استخدامه لتحديد مورد (قديم أو جديد) يحتوي على المحتوى المذكور (ربما مختلط مع محتوى آخر). يجب أن يكون المورد المذكور متطابقًا أو تابعًا لما xيعرّف". " مورد y هو تابع لمورد x " عادةً ما لا يتم تنفيذه بالضرورة بجعل y a subpath of x (على سبيل المثال x = /fooو y = /foo/bar) وتعديل التمثيل (التمثيلات) لمورد x ليعكس الوجود من مورد جديد ، على سبيل المثال مع ارتباط تشعبي إلى yالموارد وبعض البيانات الوصفية. هذا الأخير فقط ضروري لتصميم جيد ، حيث أن عناوين URL معتمة في REST - من المفترض أن تستخدم hypermedia بدلاً من إنشاء عنوان URL من جانب العميل لاجتياز الخدمة على أي حال.

في REST ، لا يوجد شيء اسمه مورد يحتوي على "محتوى". أشير باسم "المحتوى" إلى البيانات التي تستخدمها الخدمة لتقديم التقديمات باستمرار. يتكون عادةً من بعض الصفوف ذات الصلة في قاعدة بيانات أو ملف (على سبيل المثال ملف صورة). الأمر متروك للخدمة لتحويل محتوى المستخدم إلى شيء يمكن للخدمة استخدامه ، على سبيل المثال تحويل حمولة JSON إلى عبارات SQL.

الإجابة الأصلية (قد تكون أسهل في القراءة) :

PUT /something(إذا كان /somethingموجودًا بالفعل): "خذ كل ما لديك /somethingواستبدله بما أعطي لك".

PUT /something(إذا /somethingلم تكن موجودة بالفعل): "خذ ما أعطي لك ووضعه في /something."

POST /something: "خذ ما أعطي لك ووضعه في أي مكان تريده /somethingطالما أنك تعطيني عنوان URL الخاص به عندما تنتهي من ذلك".


بصورة شاملة:

يمكن استخدام كل من PUT و POST لإنشاء.

عليك أن تسأل "ما هي الإجراءات التي تقوم بها؟" لتمييز ما يجب أن تستخدمه. لنفترض أنك تصمم واجهة برمجة تطبيقات لطرح الأسئلة. إذا كنت تريد استخدام POST ، فستفعل ذلك إلى قائمة الأسئلة. إذا كنت تريد استخدام PUT ، فستفعل ذلك إلى سؤال معين.

يمكن استخدام كلاهما عظيمًا ، لذا يجب استخدامهما في تصميم RESTful:

لا تحتاج إلى دعم كل من PUT و POST.

الذي يستخدم متروك لكم. ولكن تذكر فقط استخدام الرمز الصحيح بناءً على الكائن الذي تشير إليه في الطلب.

بعض الاعتبارات:

  • هل تقوم بتسمية كائنات URL التي تقوم بإنشائها بشكل صريح ، أم تسمح للخادم بتحديدها؟ إذا سمحت لهم ، استخدم PUT. إذا سمحت للخادم أن يقرر ثم استخدم POST.
  • PUT هو idempotent ، لذلك إذا وضعت كائن مرتين ، فإنه ليس له أي تأثير. هذه ملكية لطيفة ، لذا سأستخدم PUT متى أمكن ذلك.
  • يمكنك تحديث أو إنشاء مورد باستخدام PUT مع نفس عنوان URL الكائن
  • مع POST ، يمكن أن يكون لديك طلبان قادمان في نفس الوقت لإجراء تعديلات على عنوان URL ، وقد يقوما بتحديث أجزاء مختلفة من الكائن.

مثال:

كتبت ما يلي كجزء من إجابة أخرى على SO حول هذا :

بريد:

تستخدم لتعديل وتحديث مورد

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

لاحظ أن ما يلي هو خطأ:

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

إذا لم يتم إنشاء عنوان URL بعد ، فيجب ألا تستخدم POST لإنشائه أثناء تحديد الاسم. يجب أن يؤدي هذا إلى خطأ "لم يتم العثور على المورد" لأن <new_question> غير موجود حتى الآن. يجب وضع <new_question> على الخادم أولاً.

يمكنك رغم ذلك القيام بشيء من هذا القبيل لإنشاء موارد باستخدام POST:

POST /questions HTTP/1.1
Host: www.example.com/

لاحظ أنه في هذه الحالة ، لم يتم تحديد اسم المورد ، فسيتم إرجاع مسار عنوان الكائنات الجديدة إليك.

ضع:

تُستخدم لإنشاء مورد أو استبداله. بينما تحدد الموارد URL الجديد.

للحصول على مورد جديد:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

لاستبدال مورد موجود:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/

يستند قرار استخدام PUT أو POST لإنشاء مورد على خادم مزود بـ HTTP + REST API إلى من يملك بنية عنوان URL. إذا كان العميل يعرف ، أو يشارك في تعريف ، فإن بنية عنوان URL هي اقتران غير ضروري شبيه بالاقتران غير المرغوب فيه التي تنشأ من بنية SOA. إن الفرار من أنواع الوصلات هو السبب الذي يجعل REST شائعًا جدًا. ولذلك ، فإن الطريقة الصحيحة لاستخدامها هي POST. هناك استثناءات لهذه القاعدة وتحدث عندما يرغب العميل في الاحتفاظ بالسيطرة على بنية الموقع للموارد التي ينشرها. هذا نادر ومن المحتمل أن يكون هناك شيء آخر غير صحيح.

عند هذه النقطة ، سيقول بعض الأشخاص أنه إذا تم استخدام RESTful-URL ، فإن العميل يعرف عنوان URL للمورد ، وبالتالي يكون PUT مقبولًا. بعد كل شيء ، هذا هو السبب الكنسي ، تطبيع ، روبي على القضبان ، وعناوين URL دجانغو مهمة ، والنظر في API تويتر ... بلاه بلاه بلاه. يحتاج هؤلاء الأشخاص إلى فهم أنه لا يوجد شيء اسمه عنوان URL مريح وأن روي فيلدنج نفسه ينص على ما يلي :

يجب ألا تقوم واجهة برمجة تطبيقات REST بتعريف أسماء المصادر الثابتة أو التسلسلات الهرمية (اقتران واضح للعميل والخادم). يجب أن تتمتع الخوادم بحرية التحكم في مساحة الاسم الخاصة بها. بدلاً من ذلك ، اسمح للخوادم بتوجيه العملاء حول كيفية إنشاء عناوين URI المناسبة ، مثل ما يحدث في نماذج HTML ونماذج URI ، من خلال تحديد تلك التعليمات في أنواع الوسائط وعلاقات الارتباط. [الفشل هنا يعني ضمناً أن العملاء يفترضون بنية مورد بسبب معلومات خارج النطاق ، مثل معيار خاص بمجال معين ، وهو المعادل للبيانات المكافئ للاقتران الوظيفي لـ RPC].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

إن فكرة RESTful-URL هي في الواقع انتهاك لـ REST لأن الخادم مسؤول عن بنية عنوان URL ويجب أن يكون حراً في تقرير كيفية استخدامه لتجنب الاقتران. إذا كان هذا يربكك تقرأ عن أهمية اكتشاف الذات على تصميم واجهة برمجة التطبيقات.

يأتي استخدام POST لإنشاء الموارد مع اعتبار التصميم نظرًا لأن POST ليس معتدلاً. هذا يعني أن تكرار POST عدة مرات لا يضمن نفس السلوك في كل مرة. هذا يخيف الناس في استخدام PUT لإنشاء الموارد عندما لا ينبغي. انهم يعرفون أنه من الخطأ (POST هو CREATE) ولكنهم يفعلون ذلك على أي حال لأنهم لا يعرفون كيفية حل هذه المشكلة. يتم توضيح هذا القلق في الحالة التالية:

  1. العميل POST مورد جديد إلى الخادم.
  2. يعالج الخادم الطلب ويرسل استجابة.
  3. العميل لا يتلقى الاستجابة.
  4. الخادم غير مدرك لم يتلق العميل الاستجابة.
  5. ليس لدى العميل عنوان URL للمورد (لذلك PUT ليس خيارًا) ويكرر POST.
  6. POST ليس عديم الشأن والخادم ...

الخطوة 6 هي المكان الذي يشيع فيه الناس عادة حول ما يجب القيام به. ومع ذلك ، لا يوجد سبب لإنشاء kludge لحل هذه المشكلة. بدلاً من ذلك ، يمكن استخدام HTTP كما هو محدد في RFC 2616 ويجيب الخادم:

10.4.10 409 نزاع

تعذر إكمال الطلب بسبب تعارض مع الحالة الحالية للمورد. لا يُسمح بهذا الرمز إلا في الحالات التي يُتوقع فيها أن يتمكن المستخدم من حل التعارض وإعادة إرسال الطلب. وينبغي أن تشمل هيئة الاستجابة بما فيه الكفاية

المعلومات للمستخدم للتعرف على مصدر الصراع. من الناحية المثالية ، سيشمل كيان الاستجابة معلومات كافية للمستخدم أو وكيل المستخدم لإصلاح المشكلة ؛ ومع ذلك ، قد لا يكون ذلك ممكنًا وغير مطلوب.

من المرجح أن تحدث التعارضات استجابة لطلب PUT. على سبيل المثال ، إذا كان يتم استخدام تعيين الإصدارات وكان الكيان قيد الاستخدام PUT يتضمَّن تغييرات في مورد يتعارض مع تلك التي قدمها طلب سابق (طرف ثالث) ، فقد يستخدم الخادم استجابة 409 للإشارة إلى أنه لا يمكنه إكمال الطلب . في هذه الحالة ، من المحتمل أن يحتوي كيان الاستجابة على قائمة بالاختلافات بين النسختين في شكل محدد بواسطة استجابة نوع المحتوى.

الرد على رمز الحالة لـ 409 Conflict هو الملجأ الصحيح للأسباب التالية :

  • يُعد إجراء POST للبيانات التي تحتوي على معرف يتطابق مع مورد موجود بالفعل في النظام "تعارضًا مع الحالة الحالية للمصدر".
  • بما أن الجزء المهم هو أن يفهم العميل أن الخادم لديه المورد وأن يتخذ الإجراء المناسب. هذا هو "الموقف (الأوضاع) حيث من المتوقع أن يتمكن المستخدم من حل التعارض وإعادة إرسال الطلب."
  • إن الاستجابة التي تحتوي على عنوان URL للمورد ذي المعرف المتعارض والشروط المسبقة الملائمة للمورد سوف توفر "معلومات كافية للمستخدم أو وكيل المستخدم لإصلاح المشكلة" وهي الحالة المثالية لكل RFC 2616.

تحديث يستند إلى إصدار RFC 7231 لاستبدال 2616

تم تصميم RFC 7231 ليحل محل 2616 وفي المقطع 4.3.3 يصف الاستجابة المحتملة التالية لـ POST

إذا كانت نتيجة معالجة POST تكافئ تمثيلًا لمورد موجود ، فيمكن لخادم الأصل إعادة توجيه وكيل المستخدم إلى ذلك المورد عن طريق إرسال استجابة 303 (انظر غير ذلك) مع معرف المورد الموجود في حقل الموقع. هذا له فوائد توفير وكيل المستخدم معرّفًا للموارد ونقل التمثيل عبر طريقة أكثر قابلية للتخزين المؤقت المشترك ، على الرغم من تكلفة طلب إضافي إذا لم يكن وكيل المستخدم يحتوي بالفعل على تمثيل مؤقت.

قد يكون من المغري الآن إرجاع 303 ببساطة في حالة تكرار POST. ومع ذلك، فإن العكس هو الصحيح. لن يكون إرجاع رقم 303 مفيدًا إلا إذا كانت هناك طلبات إنشاء متعددة (إنشاء موارد مختلفة) تعرض المحتوى نفسه.مثال على ذلك هو "شكرًا لك على إرسال رسالة الطلب" التي تفيد بأن العميل لا يحتاج إلى إعادة التنزيل في كل مرة. لا يزال RFC 7231 يحتفظ في القسم 4-2-2 بأن POST لا يجب أن يكون متعطلاً ويواصل الحفاظ على أنه يجب استخدام POST لإنشاء.

لمزيد من المعلومات حول هذا ، اقرأ هذه article .


بالإضافة إلى الاختلافات المقترحة من قبل الآخرين ، أريد إضافة واحدة أخرى.

في طريقة POST يمكنك إرسال params body فيform-data

في طريقة PUT لديك لإرسال params الجسم فيx-www-form-urlencoded

رأس Content-Type:application/x-www-form-urlencoded

وفقًا لذلك ، لا يمكنك إرسال ملفات أو بيانات متعددة الأجزاء في أسلوب PUT

تصحيح

نوع المحتوى "application / x-www-form-urlencoded" غير فعال لإرسال كميات كبيرة من البيانات الثنائية أو نص يحتوي على أحرف غير ASCII. يجب استخدام نوع المحتوى "multipart / form-data" لإرسال النماذج التي تحتوي على ملفات وبيانات غير ASCII وبيانات ثنائية.

مما يعني إذا كان لديك لتقديم

الملفات ، وبيانات غير ASCII ، والبيانات الثنائية

يجب عليك استخدام طريقة POST


بالمختصر:

PUT هو idempotent ، حيث تكون حالة المورد هي نفسها إذا تم تنفيذ العملية نفسها مرة واحدة أو عدة مرات.

POST هي غير عديمة القيمة ، حيث قد تصبح حالة الموارد مختلفة إذا تم تنفيذ العملية عدة مرات مقارنة بتنفيذ مرة واحدة.

القياس مع استعلام قاعدة البيانات

PUT يمكنك التفكير في تشابه "UPDATE STUDENT SET address =" abc "حيث id =" 123 "؛

POST يمكنك التفكير في شيء مثل "INSERT INTO STUDENT (الاسم والعنوان) VALUES (" abc "،" xyzzz ")؛

يتم إنشاء معرف الطالب تلقائيًا.

باستخدام PUT ، إذا تم تنفيذ نفس الاستعلام عدة مرات أو مرة واحدة ، تظل حالة جدول الطالب كما هي.

في حالة POST ، إذا تم تنفيذ نفس الاستعلام عدة مرات ، يتم إنشاء سجلات طالب متعددة في قاعدة البيانات وتغيير حالة قاعدة البيانات على كل تنفيذ استعلام "INSERT".

ملاحظة: PUT يحتاج إلى موقع مورد (بالفعل مورد) يجب أن يحدث التحديث ، في حين لا يتطلب POST ذلك. لذا فإن POST البديهي يهدف إلى إنشاء مورد جديد ، في حين أن PUT مطلوبة لتحديث الموارد الموجودة بالفعل.

قد يأتي البعض مع أنه يمكن إجراء التحديثات باستخدام POST. لا توجد قاعدة صلبة أي واحدة لاستخدام التحديثات أو أي واحد لاستخدامه في إنشاء. مرة أخرى هذه هي الاتفاقيات ، وبشكل حدسي أنا أميل مع المنطق المذكور أعلاه ومتابعته.


سأهبط مع ما يلي:

PUT يشير إلى مورد ، يحددها URI. في هذه الحالة ، تقوم بتحديثه. إنه جزء من الأفعال الثلاثة التي تشير إلى الموارد - قم بحذف والتخلص من الأثنين الآخرين.

POST هي في الأساس رسالة شكل حر ، مع تعريف معناها "خارج النطاق". إذا كان يمكن تفسير الرسالة على أنها إضافة مورد إلى دليل ، فسيكون ذلك أمرًا مقبولًا ، ولكن تحتاج في الأساس إلى فهم الرسالة التي ترسلها (النشر) لمعرفة ما سيحدث مع المورد.

نظرًا لأن PUT و GET و DELETE يشيران إلى أحد الموارد ، فإنهما أيضًا من خلال التعريف المحدد.

يمكن أن يقوم POST بالوظائف الثلاثة الأخرى ، ولكن سيتم فقدان دلالات الطلب على الوسطاء مثل caches و proxies. وينطبق هذا أيضًا على توفير الأمان على المورد ، نظرًا لأن عنوان URI الخاص بالوظيفة لا يشير بالضرورة إلى المورد الذي يقدمه (يمكن رغم ذلك).

لا يحتاج PUT إلى أن يكون إنشاء ؛ قد تتعرض الخدمة للخطأ إذا لم يكن المورد قد تم إنشاؤه بالفعل ، ولكن بخلاف ذلك قم بتحديثه. أو بالعكس - قد ينشئ المورد ، ولكن لا يسمح بالتحديثات. الشيء الوحيد المطلوب عن PUT هو أنه يشير إلى مورد معين ، وحملته هي تمثيل ذلك المورد. يعني PUT الناجحة (منع التدخل) أن GET استرداد نفس المورد.

تحرير: شيء آخر - يمكن إنشاء PUT ، ولكن إذا كان كذلك ، يجب أن يكون المعرّف معرفًا طبيعيًا - AKA عنوان بريد إلكتروني. بهذه الطريقة عندما تضع PUT مرتين ، فإن الوضع الثاني هو تحديث لأول مرة. هذا يجعلها عاطلة .

إذا تم إنشاء المعرف (معرف الموظف الجديد ، على سبيل المثال) ، فسيقوم PUT الثاني بنفس عنوان URL بإنشاء سجل جديد ، والذي ينتهك قاعدة المتسلل. في هذه الحالة ، يكون الفعل POST ، وتكون الرسالة (وليس المورد) هي إنشاء مورد باستخدام القيم المحددة في هذه الرسالة.


سوف يستخدم Ruby on Rails 4.0 طريقة "PATCH" بدلاً من PUT لإجراء تحديثات جزئية.

يقول RFC 5789 عن PATCH (منذ 1995):

هناك طريقة جديدة ضرورية لتحسين التشغيل البيني ومنع الأخطاء. تم بالفعل تعريف أسلوب PUT على الكتابة فوق مورد بهيئة جديدة كاملة ، ولا يمكن إعادة استخدامه لإجراء تغييرات جزئية. بخلاف ذلك ، قد يتم الخلط بين الخوادم الوكيلة وذاكرة التخزين المؤقت ، وحتى العملاء والخوادم ، كنتيجة للعملية. يتم استخدام POST بالفعل ولكن بدون إمكانية التشغيل البيني (على سبيل المثال ، لا توجد طريقة قياسية لاكتشاف دعم تنسيق التصحيح). تم ذكر PATCH في مواصفات HTTP السابقة ، ولكن لم يتم تعريفها بشكل كامل.

" Edge Rails: PATCH هي طريقة HTTP الأساسية الجديدة للتحديثات " يشرحها.


في معظم الأحيان ، سوف تستخدمها على النحو التالي:

  • POST مورد إلى مجموعة
  • ضع موردًا محددًا عن طريق مجموعة /: id

فمثلا:

  • وظيفة / البنود
  • PUT / items / 1234

في كلتا الحالتين ، يحتوي نص الطلب على بيانات للمورد المراد إنشاؤه أو تحديثه. يجب أن يكون واضحًا من أسماء المسارات التي لا يكون POST فيها محددًا (إذا نسميها 3 مرات ، فسيؤدي ذلك إلى إنشاء 3 كائنات) ، ولكن PUT هو idempotent (إذا كنت تسميها 3 مرات فإن النتيجة هي نفسها). يُستخدم PUT غالبًا لعملية "upsert" (إنشاء أو تحديث) ، ولكن يمكنك دائمًا عرض خطأ 404 إذا كنت تريد استخدامه فقط للتعديل.

لاحظ أن POST "ينشئ" عنصرًا جديدًا في المجموعة ، و PUT "يستبدل" عنصرًا في عنوان URL محدد ، ولكن من المعتاد جدًا استخدام PUT لإجراء تعديلات جزئية ، أي استخدامه فقط لتحديث الموارد الموجودة و فقط تعديل الحقول المضمنة في الجسم (تجاهل الحقول الأخرى). هذا غير صحيح من الناحية الفنية ، إذا كنت تريد أن تكون متطوعة ، REST يجب استبدال PUTCH للتحديث الجزئي بدلاً من المورد بالكامل. أنا شخصيا لا أهتم كثيرا بقدر ما هو سلوك واضح ومتسق في جميع نقاط نهاية API الخاصة بك.

تذكر أن REST هي مجموعة من الاتفاقيات والإرشادات للحفاظ على واجهة برمجة التطبيقات بسيطة. إذا انتهى بك الأمر إلى عمل معقد لمجرد التحقق من مربع "RESTfull" ، فإنك بذلك تهزم الهدف ؛)


من المفترض أن تكون الدلالات مختلفة ، في أن "PUT" ، مثل "GET" يفترض أن يكون idempotent - بمعنى ، يمكنك نفس طلب PUT بالضبط عدة مرات وستكون النتيجة كما لو أنك قمت بتنفيذها مرة واحدة فقط.

سأصف الاتفاقيات التي أعتقد أنها الأكثر استخدامًا وأكثرها فائدة:

عندما تضع موردًا في عنوان URL معين ، فإن ما يحدث هو أنه يجب حفظه على عنوان URL هذا ، أو شيء ما على هذا المنوال.

عند POST إلى مورد في عنوان URL معين ، غالبًا ما تنشر جزءًا من المعلومات ذات الصلة إلى عنوان URL هذا. هذا يعني أن المورد الموجود على عنوان URL موجود بالفعل.

على سبيل المثال ، عندما تريد إنشاء مجموعة بث جديدة ، يمكنك وضعها في بعض عناوين URL. ولكن عندما تريد إرسال رسالة إلى مجموعة بث موجودة ، يمكنك POST إلى عنوان URL الخاص بها.

أما بالنسبة لتعديل خصائص الدفق ، فيمكنك القيام بذلك باستخدام إما PUT أو POST. في الأساس ، استخدم فقط "PUT" عندما تكون العملية idempotent - وإلا استخدم POST.

مع ذلك ، لاحظ أن جميع المتصفحات الحديثة لا تدعم أفعال HTTP غير GET أو POST.


يستخدم كلاهما لنقل البيانات بين العميل والخادم ، ولكن هناك اختلافات دقيقة بينهما ، وهما:

القياس:

  • PUT أي تأخذ ووضع فيها.
  • ما بعد إرسال البريد في مكتب البريد .


أنا أحب هذه النصيحة ، من تعريف RFC 2616 من PUT :

وينعكس الفرق الأساسي بين طلبات POST و PUT في المعنى المختلف لعنوان URI. يحدد URI في طلب POST المورد الذي سيعالج الكيان المرفق. قد يكون هذا المورد عبارة عن عملية قبول للبيانات أو مدخل إلى بروتوكول آخر أو كيان منفصل يقبل التعليقات التوضيحية. في المقابل ، يحدد URI في طلب PUT الكيان المرفق مع الطلب - يعرف وكيل المستخدم ما هو المقصود من URI ويجب ألا يحاول الخادم تطبيق الطلب على بعض الموارد الأخرى.

هذه المشاعر مع النصيحة الأخرى هنا ، هي أن أفضل طريقة لتطبيق PUT على الموارد التي لديها بالفعل اسم ، و POST جيد لإنشاء كائن جديد تحت مورد موجود (وترك اسم الخادم عليه).

أنا أفسر هذا ، ومتطلبات idempotency على PUT ، يعني أن:

  • يعد POST أمرًا جيدًا لإنشاء كائنات جديدة ضمن مجموعة (ولا يجب أن يكون إنشاء idempotent)
  • PUT جيد لتحديث الكائنات الموجودة (ويجب أن يكون التحديث معرفًا)
  • يمكن استخدام POST أيضًا لتحديثات غير عديمة القيمة للكائنات الموجودة (خاصة ، تغيير جزء من كائن بدون تحديد الشيء بالكامل - إذا فكرت في الأمر ، فإن إنشاء عضو جديد في مجموعة هو في الواقع حالة خاصة من هذا النوع من التحديث ، من وجهة نظر المجموعة)
  • يمكن أيضًا استخدام PUT لإنشاء إذا وفقط إذا سمحت للعميل بتسمية المورد. ولكن نظرًا لأن عملاء REST لا يفترض بهم افتراضات حول بنية عنوان URL ، فهذا أقل في روح الأشياء المقصودة.

القراء الجدد في هذا الموضوع سيواجههم النقاش اللامتناهي حول ما يجب فعله ، والغياب النسبي للدروس المستفادة من التجربة. حقيقة أن REST هو "المفضل" على SOAP هو ، على ما أعتقد ، على مستوى عال من التعلم من الخبرة ، ولكن الخير الذي يجب أن نتقدم من هناك؟ إنها 2016. كانت أطروحة روي في عام 2000. ما الذي قمنا بتطويره؟ هل كان ذلك ممتعا؟ هل كان من السهل الاندماج مع؟ من أجل دعم؟ هل سيتعامل مع ارتفاع الهواتف الذكية والاتصالات المتنقلة غير المستقرة؟

وفقًا لـ ME ، لا يمكن الاعتماد على الشبكات الواقعية. طلبات المهلة. يتم إعادة ضبط الاتصالات. الشبكات تنخفض لساعات أو أيام في كل مرة. تذهب القطارات إلى أنفاق مع مستخدمي الهواتف المحمولة على متنها. لأي طلب معين (كما هو معتاد في كل هذه المناقشة) يمكن أن يقع الطلب في الماء في طريقه ، أو يمكن أن تقع الاستجابة في الماء في طريق عودته. في ظل هذه الظروف ، فإن إصدار طلبات PUT و POST و DELETE مباشرة ضد الموارد الفنية لطالما وصفني بالوحشية والسذاجة.

لا يفعل HTTP شيئًا لضمان إتمام استجابة الطلب بشكلٍ موثوق ، وهذا أمر جيد نظرًا لأن هذه الوظيفة مناسبة للتطبيقات الواعية للشبكات. تطوير مثل هذا التطبيق ، يمكنك القفز من خلال الأطواق لاستخدام PUT بدلا من POST ، ثم المزيد من الأطواق لإعطاء نوع معين من الأخطاء على الخادم إذا كنت تكتشف طلبات مكررة. عند العودة إلى العميل ، يجب عليك القفز من خلال الأطواق لتفسير هذه الأخطاء ، وإعادة صياغتها ، وإعادة التحقق منها وإعادة نشرها.

أو يمكنك القيام بذلك : ضع في اعتبارك الطلبات غير الآمنة كموارد فردية لمستخدم واحد (دعنا نسميها الإجراءات). يطلب العملاء "إجراءً" جديدًا على مورد موضوعي مع POST فارغ إلى المورد. سيتم استخدام POST فقط لهذا الغرض. وبمجرد أن يمتلك العميل URI من الإجراء المصغّر حديثًا ، يطرح العميل الطلب غير الآمن إلى معرِّف الموارد المنتظم الإجراء ، وليس المورد المستهدف . إن حل هذا الإجراء وتحديث المورد "الحقيقي" هو بشكل صحيح مهمة واجهة برمجة التطبيقات ، ومن هنا يتم فصله عن الشبكة غير الموثوق بها.

يقوم الخادم بالعمل ، ويعيد الاستجابة ويخزنها مقابل عنوان URI المتفق عليه . إذا حدث أي خطأ ، فإن العميل يكرر الطلب (السلوك الطبيعي!) ، وإذا كان الخادم قد شاهده بالفعل ، فإنه يكرر الاستجابة المخزنة ولا يفعل شيئًا آخر .

ستكتشف بسرعة التشابه بوعود: نقوم بإنشاء العنصر النائب وإرجاعه للنتيجة قبل القيام بأي شيء. أيضا مثل الوعد ، يمكن أن ينجح العمل أو يفشل مرة واحدة ، ولكن يمكن استخلاص نتائجها مرارا وتكرارا.

والأفضل من ذلك كله ، أننا نمنح إرسال وتلقي التطبيقات فرصة لربط الإجراء المحدد بشكل فريد بالتفرد في بيئاتها الخاصة. ويمكننا أن نبدأ في الطلب ، والتنفيذ! ، والسلوك المسؤول من العملاء: كرر طلباتك بقدر ما تريد ، ولكن لا تذهب لتوليد إجراء جديد حتى تكون في حيازتك نتيجة نهائية من القائمة.

على هذا النحو ، العديد من المشاكل الشائكة تختفي. لن تؤدي طلبات الإدراج المتكررة إلى إنشاء نسخ مكررة ، ولا ننشئ المورد الحقيقي حتى نمتلك البيانات. (يمكن أن تظل أعمدة قاعدة البيانات غير صالحة). لن تتسبب طلبات التحديث المتكررة في الوصول إلى حالات غير متوافقة ولن تستبدل التغييرات اللاحقة. يمكن للعملاء (إعادة) إحضار وتأكيد عملية التثبيت الأصلية لأي سبب من الأسباب (تحطم العميل ، فقد الاستجابة ، وما إلى ذلك).

يمكن لطلبات الحذف المتتالية مشاهدة ومعالجة التأكيد الأصلي ، دون الوصول إلى خطأ 404. إذا استغرقت الأمور وقتًا أطول مما هو متوقع ، فيمكننا الاستجابة مؤقتًا ، ولدينا مكان يمكن للعميل التحقق منه للحصول على النتيجة النهائية. اجمل جزء من هذا النمط هو ملكه الكونغ فو (باندا). نأخذ نقطة ضعف ، الميل للعملاء لتكرار طلب في أي وقت لا يفهمون الاستجابة ، وتحويلها إلى قوة :-)

قبل أن تخبرني أن هذا ليس RESTful ، يرجى النظر في الطرق العديدة التي تحترم بها مبادئ REST. لا يقوم العملاء بإنشاء عناوين URL. تظل واجهة برمجة التطبيقات قابلة للاكتشاف ، ولكن مع تغيير بسيط في الدلالات. الأفعال HTTP تستخدم بشكل مناسب. إذا كنت تعتقد أن هذا تغيير كبير في التنفيذ ، يمكنني أن أخبرك من التجربة أنه ليس كذلك.

إذا كنت تعتقد أن لديك كميات هائلة من البيانات لتخزينها ، دعنا نتحدث عن الأحاديث: تأكيد التحديث النموذجي هو جزء من الكيلوبايت. يعطيك HTTP حاليًا دقيقة أو دقيقتين للإجابة بشكل قاطع. حتى إذا كنت تخزن فقط الإجراءات لمدة أسبوع ، فإن العملاء لديهم فرصة كبيرة للحاق. إذا كان لديك وحدات تخزين عالية جدًا ، فقد ترغب في تخزين قيمة أساسية مخصصة متوافقة مع حمض ، أو حل في الذاكرة.


في خطر إعادة صياغة ما سبق قوله ، يبدو من المهم أن نتذكر أن PUT يعني أن العميل يتحكم في ما سيؤول إليه عنوان URL ، عند إنشاء مورد. لذلك فإن جزءًا من الاختيار بين PUT و POST سيكون حول المبلغ الذي يمكنك الوثوق به من العميل لتقديم عنوان URL صحيح ومُطابق ومتوافق مع أي نظام عنوان URL الخاص بك.

عندما لا يمكنك الوثوق التام بالعميل للقيام بالشيء الصحيح ، سيكون من الأنسب استخدام POST لإنشاء عنصر جديد ثم إرسال عنوان URL مرة أخرى إلى العميل في الاستجابة.


يبدو أن هناك بعض الارتباك دائمًا حول وقت استخدام HTTP POST في مقابل طريقة HTTP PUT لخدمات REST. سيحاول معظم المطورين ربط عمليات CRUD مباشرة بطرق HTTP. سأزعم أن هذا غير صحيح ولا يمكن للمرء ببساطة ربط مفاهيم CRUD بطرق HTTP. هذا هو:

Create => HTTP PUT
Retrieve => HTTP GET
Update => HTTP POST
Delete => HTTP DELETE

صحيح أنه يمكن تعيين R (etrieve) و D (elete) لعمليات CRUD مباشرة إلى أساليب HTTP GET و DELETE على التوالي. ومع ذلك ، يكمن الارتباك في عمليات C (reate) و U (التحديث). في بعض الحالات ، يمكن للمرء استخدام PUT لإنشاء في حين أنه في حالات أخرى سوف تكون مطلوبة POST. يكمن الغموض في تعريف طريقة HTTP PUT مقابل طريقة HTTP POST.

وفقاً لمواصفات HTTP 1.1 يجب أن تكون أساليب GET و HEAD و DELETE و PUT disempotent ، وأن أسلوب POST لا يعدّ مكافئًا. وهذا يعني أن العملية هي عديمة القيمة إذا أمكن تنفيذها على مورد مرة واحدة أو عدة مرات وإرجاع الحالة نفسها من هذا المورد دائمًا. في حين أن عملية غير عادلة يمكن أن تعيد حالة معدلة للمصدر من طلب إلى آخر. ومن ثم ، لا يوجد ضمان في حالة عدم الانفتاح ، بأن الشخص سيحصل على نفس حالة المورد.

استنادًا إلى تعريف المعرف أعلاه ، فإن استخدامي لأسلوب HTTP PUT مقابل استخدام طريقة HTTP POST لخدمات REST هو: استخدم طريقة PUT HTTP عندما:

The client includes all aspect of the resource including the unique identifier to uniquely identify the resource. Example: creating a new employee.
The client provides all the information for a resource to be able to modify that resource.This implies that the server side does not update any aspect of the resource (such as an update date).

في كلتا الحالتين ، يمكن إجراء هذه العمليات عدة مرات مع نفس النتائج. هذا لن يتم تغيير المورد عن طريق طلب العملية أكثر من مرة. ومن ثم ، عملية idempotent صحيح. استخدم طريقة HTTP POST عندما:

The server will provide some information concerning the newly created resource. For example, take a logging system. A new entry in the log will most likely have a numbering scheme which is determined on the server side. Upon creating a new log entry, the new sequence number will be determined by the server and not by the client.
On a modification of a resource, the server will provide such information as a resource state or an update date. Again in this case not all information was provided by the client and the resource will be changing from one modification request to the next. Hence a non idempotent operation.

استنتاج

لا ترتبط بشكل مباشر وتخطيط عمليات CRUD إلى أساليب HTTP لخدمات REST. يجب أن يستند استخدام أسلوب PUT HTTP مقابل طريقة HTTP POST على الجانب الافتراضي لهذه العملية. بمعنى ، إذا كانت العملية هي idempotent ، فاستخدم طريقة HTTP PUT. إذا كانت العملية غير مرتبطة ، فاستخدم طريقة HTTP POST.


يشبه POST نشر رسالة إلى صندوق بريد أو نشر بريد إلكتروني إلى قائمة انتظار البريد الإلكتروني. PUT يشبه عند وضع كائن في حفرة cubby أو مكان على رف (له عنوان معروف).

مع POST ، أنت تنشر على عنوان QUEUE أو COLLECTION. مع PUT ، أنت تضع عنوان ITEM.

PUT هو المتكافئ. يمكنك إرسال الطلب 100 مرة ولن يهم. POST ليس عديم المعتقد. إذا أرسلت الطلب 100 مرة ، فستحصل على 100 بريد إلكتروني أو 100 حرف في صندوق بريدك.

قاعدة عامة: إذا كنت تعرف معرف العنصر أو اسمه ، فاستخدم PUT. إذا كنت تريد تعيين معرف أو اسم العنصر بواسطة الطرف المستقبل ، فاستخدم POST.





put