Desain REST API untuk halaman web dengan penyihir


11

Saya memiliki halaman web dengan format wizard. Tombol pengiriman ke API akan ada di langkah ke-4 wizard. Namun saya ingin data yang dimasukkan disimpan dalam basis data sebelum pindah ke langkah selanjutnya dalam panduan. Saya juga ingin API REST berfungsi untuk halaman yang memiliki satu tab.

Jadi saya merancang API untuk mengambil parameter kueri tindakan = konsep atau kirim. Jika tindakan adalah konsep, hanya bidang tertentu yang wajib. Jika tindakan dikirimkan, semua bidang wajib diisi. Validasi di lapisan layanan REST API akan dilakukan berdasarkan parameter kueri. Sepertinya saya harus secara eksplisit menentukan klausa if / else dalam dokumentasi. Apakah ini bentuk desain RESTful yang dapat diterima? Apa yang akan menjadi desain terbaik dengan persyaratan ini?


3
Mengapa data sementara perlu disimpan dalam DB?
Dan1701

2
@ Dan1701: sehingga Anda dapat melanjutkan wisaya dari komputer lain. Saat mengisi formulir yang panjang dan rumit, mungkin perlu beberapa hari untuk menyelesaikan semua data yang diperlukan, karena pengguna mungkin tidak memiliki semua data yang diperlukan, atau pengguna mungkin perlu mengumpulkan file tambahan untuk mengunggah dari tempat yang berbeda. Jika Anda dapat melanjutkan dari perangkat yang berbeda, Anda dapat memuat wizard untuk mengunggah foto dari ponsel, dan terus mengetik deskripsi / argumen panjang dengan keyboard sungguhan di desktop, dll.
Lie Ryan

Dalam hal ini, saya pikir jawaban @ guillaume31 masuk akal.
Dan1701

Jawaban:


7

Karena Anda ingin mempertahankan hal-hal di server di antara langkah-langkah wizard, tampaknya sangat diterima untuk mempertimbangkan setiap langkah sebagai sumber daya yang terpisah. Sesuatu di sepanjang garis ini:

POST /wizard/123/step1
POST /wizard/123/step2
POST /wizard/123/step3

Dengan menyertakan tautan hypermedia dalam respons, Anda dapat memberi tahu klien tentang apa yang dapat dilakukannya setelah langkah ini - maju atau mundur untuk langkah perantara, dan tidak ada apa pun untuk langkah terakhir. Anda dapat melihat contohnya pada Gambar 5 di sini .


Saya menggunakan Angular untuk UI. Jadi saya tidak yakin seberapa membantu mesin negara. Tapi saya pikir sumber daya berbasis langkah tampaknya lebih bermakna daripada mengelola tabel lain. Juga, saya harus bisa mengirimkan semuanya dalam satu langkah. Akan mencobanya pada desain ini hari ini. Terima kasih untuk bantuannya.
TechCrunch

Sama-sama. Omong-omong, pendekatan "dua tabel" tidak saling eksklusif dengan ini. Memiliki satu sumber daya HTTP per langkah tidak menentukan model objek Anda di server aplikasi, apalagi skema database. Itu hanya representasi Web.
guillaume31

1
@ TechCrunch Pada dasarnya Guillaume berarti bahwa objek / tabel yang mewakili formulir dapat dibagi menjadi beberapa bagian, di mana bagian dari model disimpan pada setiap langkah. Bahkan, Anda bisa menjadikan setiap "langkah" menjadi bentuk bagi sebagian dari keseluruhan model . Dan jika Anda mengambil pendekatan ini, itu sebenarnya membuat arsitekturnya sangat sederhana. Setiap POST ke server akan (membuat atau) memperbarui model yang sama, dan setiap GET akan memuat model yang sama, dan setiap langkah akan menjadi formulir untuk mengisi set bidang yang secara semantik bermakna (saling memiliki). Dan cukup memiliki boolean pada model untuk in_progressatau draft.
Chris Cirefice

3

Saya perlu melakukan sesuatu yang serupa beberapa waktu lalu, dan berikut ini menjelaskan apa yang akhirnya kami lakukan.

Kami memiliki dua tabel, Item dan UnfinishedItem. Ketika pengguna mengisi data dengan wizard, data disimpan dalam tabel UnfinishedItem. Pada setiap langkah panduan, server memvalidasi data yang dimasukkan selama langkah itu. Saat pengguna selesai dengan wizard, wizard merender formulir tersembunyi / baca-saja di halaman konfirmasi yang menunjukkan semua data untuk dikirimkan. Pengguna dapat meninjau halaman ini dan kembali ke langkah yang relevan untuk memperbaiki kesalahan. Setelah pengguna puas dengan entri mereka, pengguna mengklik kirim dan wisaya kemudian mengirimkan semua data di bidang formulir tersembunyi / baca saja ke server API. Ketika server API memproses permintaan ini, ia mengulangi semua validasi yang dilakukannya selama setiap langkah wizard, dan melakukan validasi tambahan yang tidak sesuai dengan langkah-langkah individual (misalnya validasi global, validasi mahal).

Keuntungan dari pendekatan dua tabel:

  • dalam database, Anda bisa memiliki batasan yang lebih ketat pada tabel Item daripada tabel UnfinishedItem; Anda tidak harus memiliki kolom opsional yang benar-benar diperlukan saat wisaya selesai.

  • Permintaan agregat di seluruh Barang jadi untuk pelaporan lebih mudah karena Anda tidak harus ingat untuk mengecualikan Item yang Belum Selesai. Dalam kasus kami, kami tidak pernah perlu melakukan permintaan agregat antara Item dan UnfinishedItems, jadi ini bukan masalah.

Kerugiannya:

  • Ini rentan terhadap duplikasi logika validasi. Kerangka kerja web yang kami gunakan, Django, membuat ini sedikit lebih tertahankan karena kami menggunakan model pewarisan dengan sedikit meta magic untuk mengubah batasan yang kita butuhkan untuk menjadi berbeda dalam Item dan UnfinishedItem. Django menghasilkan sebagian besar basis data dan validasi formulir dari model, dan kita hanya perlu meretas beberapa validasi tambahan di atasnya.

Kemungkinan lain yang telah saya pertimbangkan dan mengapa kami tidak mengikuti mereka:

  • menyimpan data dalam cookie atau penyimpanan lokal: pengguna tidak dapat melanjutkan pengirimannya dari perangkat lain atau jika mereka menghapus riwayat browser mereka
  • menyimpan UnfinishedItem sebagai data yang tidak terstruktur (misalnya JSON) pada database atau data sekunder: Saya harus mendefinisikan parsing logic dan tidak dapat menggunakan validasi model / form otomatis Django.
  • lakukan validasi per langkah di sisi klien: Saya harus menduplikasi logika validasi antara Python / Django dan JavaScript.

1
+1 untuk menunjukkan validasi pada model tipe 'konsep' dan model 'selesai'; Saya tidak memikirkan itu, dan itu adalah poin penting yang harus dipertimbangkan. Kalau tidak, Anda mungkin akan memiliki banyak ifpernyataan memeriksa status draf di seluruh validasi Anda, yang tidak akan bagus. Meskipun beberapa kerangka kerja yang sangat canggih seperti Ruby on Rails dapat secara signifikan menyederhanakan masalah itu jika diterapkan dengan benar.
Chris Cirefice

1

Saya sudah menerapkan ini dengan cara yang mirip dengan campuran solusi @ guillauma31 dan @Lie Ryan.

Berikut adalah konsep kuncinya:

  1. Ada panduan 3 langkah yang dapat dipertahankan sebagian hingga selesai.
  2. Setiap langkah memiliki sumber daya sendiri (mis .: /users/:id_user/profile/step_1.: .../step_2,, dll.)
  3. Pada setiap langkah, data dan status penyelesaian dapat diambil melalui permintaan GET dan bertahan melalui permintaan PATCH.
  4. Setiap sumber daya memiliki aturan validasinya sendiri untuk data yang dimasukkan.
  5. Setiap langkah mengembalikan kunci yang harus digunakan dalam input langkah selanjutnya untuk menjamin urutan. Setelah digunakan atau yang baru dihasilkan, token ini kedaluwarsa.
  6. Pada langkah terakhir, kami memiliki semua data yang dibutuhkan pada database dan layar konfirmasi ditampilkan. Konfirmasi ini memanggil sumber daya lain untuk menandai data sebagai lengkap (mis .:) .../profile/confirm. Sumber daya ini tidak perlu menerima semua data lagi. Itu hanya menandai data sebagai benar dan lengkap.
  7. Ada jadwal rutin yang menghapus entri tidak lengkap ini yang memiliki lebih dari beberapa hari.

Orang-orang front-end harus mengurus token untuk mendapatkan aliran bolak-balik dari penyihir bekerja.

API adalah stateless dan atom.

Untuk membuat "one step wizard" berfungsi dengan pengaturan ini, Anda harus mengubah beberapa hal, seperti menghapus aliran token atau membuat sumber daya untuk mengembalikan token berdasarkan jenis wizard atau bahkan membuat sumber daya baru hanya untuk mengisi single spesifik ini panduan langkah (seperti PUT /users/:id_user/profile/).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.