Bolehkah REST mengembalikan konten setelah POST?

89

Saya menggunakan RESTlet dan saya telah membuat sumber daya. Saya menangani POST dengan acceptRepresentationmetode overriding .

Klien harus mengirimi saya beberapa data, lalu saya menyimpannya ke DB, menyetel respons ke 201 (SUCCESS_CREATED) dan saya perlu mengembalikan beberapa data ke klien, tetapi mengembalikan jenis acceptRepresentationadalah void.

Dalam kasus saya, saya perlu mengembalikan beberapa pengenal agar klien dapat mengakses sumber daya itu.

Misalnya, jika saya memiliki sumber daya dengan URL /resourcedan klien mengirimkan permintaan POST, saya menambahkan baris baru di DB dan alamatnya seharusnya /resource/{id}. Saya perlu mengirim {id}.

Apakah saya melakukan sesuatu yang salah? Apakah prinsip REST memungkinkan untuk mengembalikan sesuatu setelah POST? Jika ya, bagaimana saya bisa melakukannya, dan jika tidak bagaimana cara menangani situasi ini?

del-boy
sumber
Lihat jawaban Thom untuk cara mengatur badan respons dari dalam acceptRepresentation ().
Avi Flax

Jawaban:

97

REST hanya mengatakan bahwa Anda harus menyesuaikan dengan antarmuka seragam. Dengan kata lain, dikatakan bahwa Anda harus melakukan apa yang seharusnya dilakukan POST sesuai spesifikasi HTTP . Berikut kutipan dari spesifikasi yang relevan,

Jika sumber daya telah dibuat di server asal, respons HARUS 201 (Dibuat) dan berisi entitas yang menjelaskan status permintaan dan merujuk ke sumber daya baru, dan header Lokasi (lihat bagian 14.30).

Seperti yang dapat Anda lihat dari sini, Anda memiliki dua tempat di mana Anda dapat menunjukkan kepada klien di mana sumber daya yang baru dibuat berada. Header Lokasi harus memiliki URL yang mengarah ke sumber daya baru dan Anda juga dapat mengembalikan entitas dengan detailnya.

Saya tidak yakin apa perbedaan antara overriding acceptRepresentation () dan overriding post () tetapi contoh ini menunjukkan bagaimana mengembalikan respons dari POST.

Darrel Miller
sumber
2
@ del-boy: Lihat jawaban Thom tentang cara menyetel badan respons dari dalam acceptRepresentation ().
Avi Flax
1
Kutipan spesifikasi HTTP tidak melarang tanggapan, jika Anda melihat di Bagian 6 sudah jelas bahwa: diizinkan: Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or response status code. An entity consists of entity-header fields and an entity-body, although some responses will only include the entity-headers.
MikeF
@MikeF Bukan niat saya untuk menyimpulkan bahwa badan tanggapan tidak diizinkan. Bagian dari spesifikasi yang saya kutip secara khusus mengatakan "dan berisi entitas". Saya seharusnya lebih jelas dalam teks saya.
Darrel Miller
16

Saya akan melupakan mengirimkan apa pun ke dalam tubuh tanggapan. Cukup setel Lokasi: ke URL (lengkap) dari sumber daya yang baru dibuat.

Deskripsi Anda menunjukkan bahwa inilah semantik Anda:

  1. POSTING sesuatu untuk membuatnya
  2. Tanggapi dengan cukup mengetahui dua hal:
    1. Bahwa penciptaan terjadi (201)
    2. Di mana menemukan hal baru (tajuk Lokasi)

Ada lagi yang tidak berguna.

cdent
sumber
Bukan berarti Wikipedia selalu merupakan sumber yang baik, tetapi itu juga menyatakan "[...] Untuk memberikan informasi tentang lokasi sumber daya yang baru dibuat. Dalam keadaan ini, tajuk Lokasi harus dikirim dengan kode status HTTP 201 atau 202 . "
Arjan
1
POST dapat menjalankan logika yang membuat satu atau lebih sumber daya. Hasil pemrosesan mungkin dibutuhkan oleh klien. Jadi, mengembalikannya dalam respons menghindari kebutuhan untuk membuat satu atau beberapa panggilan GET ke API. Data yang dibuat / diubah dengan metode POST mungkin (dan seringkali tidak) berlebihan bagi klien.
Paulo Merson
10

Dua pertanyaan berbeda:

Apakah pola aplikasi REST mendukung pengembalian data dalam POST?

Saya tidak berpikir REST secara eksplisit melarangnya, tetapi perawatan yang disukai dijabarkan dalam jawaban Darrel.

Apakah kerangka kerja RESTlet memungkinkan pengembalian data dalam POST?

Ya, meskipun mengembalikan void, dalam kelas yang memperluas Resource, Anda memiliki akses penuh ke objek objek Respon melalui metode getResponse (). Jadi Anda bisa memanggil getResponse (). SetEntity () dengan data apa pun yang Anda inginkan.

Thom
sumber
6

Keluarkan dalam format apa pun yang diminta. Itu mungkin:

<success>
    <id>5483</id>
</success>

Atau:

{ "type": "success", "id": 5483 }

Itu tergantung pada apa yang biasanya Anda lakukan. Jika mereka tidak mengharapkan datanya, mereka harus mengabaikannya, tetapi klien mana pun yang ingin menanganinya dengan benar harus bisa.

Samir Talwar
sumber
Oke, saya punya dua kemungkinan format (html dan xml). Saya tahu cara menangani jenis format yang diminta, tetapi saya tidak tahu cara menambahkan data ke respons. mewakili metode mengembalikan Representasi, jadi saya hanya mengembalikan apa pun yang saya inginkan, tetapi acceptRepresentation adalah metode kosong, jadi saya tidak dapat mengembalikan data apa pun ...
del-boy
1

Jika Anda merespons 201 Dibuat dengan badan entitas, bukan pengalihan Lokasi, sebaiknya sertakan tajuk Lokasi-Konten yang menunjuk ke sumber daya yang diwakili dalam respons.

Hal ini akan menghindari potensi kebingungan - di mana klien dapat (secara wajar) mengasumsikan bahwa entitas respons sebenarnya mewakili keadaan baru 'pencipta', dan bukan sumber daya yang dibuat.

> POST /collection
> ..new item..

< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>
Mike
sumber
3
Saya pikir Content-Location adalah untuk tujuan yang berbeda. Spesifikasi HTTP mengatakan Lokasi-Konten tidak ditentukan untuk POST dan PUT. Header Lokasi digunakan dengan 201-Create. Mengembalikan Lokasi tidak secara otomatis melakukan pengalihan, Anda memerlukan kode respons 3XX untuk itu.
Darrel Miller
1
Header lokasi digunakan (dalam respons 201) untuk menunjukkan lokasi sumber daya yang dibuat; itu tidak relevan dengan badan entitas dari respons yang menyertainya. Maksud saya adalah - jika Anda ingin menyertakan sumber daya yang dibuat dalam respons 201 itu sendiri (daripada mengarahkan / mengarahkan klien ke URI lain), maka header lokasi konten akan menjadi ide yang bagus. Ini mungkin sedikit 'membengkokkan aturan', tetapi ini lebih efisien daripada memerlukan siklus permintaan / respons lain untuk mendapatkan status sumber daya baru ke klien.
Mike
Masuk akal bagiku. Saya belum pernah menggunakan tajuk Lokasi-Konten sebelumnya.
Darrel Miller
jika klien adalah manusia dengan browser, mengembalikan 201 dengan header Lokasi tidak masuk akal. Pengguna tidak akan tahu apa yang harus dilakukan dengannya. jika klien adalah robot, ia dapat diprogram tahu bagaimana menghadapinya - seperti GET tindak lanjut di Lokasi.
bereputasi pada
3
@irreputable: Saya percaya bahwa REST dimaksudkan untuk mendesain API, di mana A tidak berarti Agen Pengguna yang mencari beberapa HTML untuk dirender.
Hermes