Apa itu middleware Rack di Ruby? Saya tidak dapat menemukan penjelasan yang baik untuk apa yang mereka maksud dengan "middleware".
ruby-on-rails
ruby
http
web-applications
rack
chrisgoyal
sumber
sumber
Jawaban:
Rak sebagai Desain
Rack middleware lebih dari "cara untuk memfilter permintaan dan respons" - ini merupakan implementasi dari pola desain pipa untuk server web menggunakan Rack .
Itu sangat bersih memisahkan berbagai tahap memproses permintaan - pemisahan kekhawatiran menjadi tujuan utama dari semua produk perangkat lunak yang dirancang dengan baik.
Sebagai contoh dengan Rack saya dapat melakukan tahapan terpisah dari pipeline melakukan:
Otentikasi : ketika permintaan datang, apakah detail login pengguna benar? Bagaimana cara memvalidasi OAuth ini, Otentikasi Dasar HTTP, nama / kata sandi?
Otorisasi : "apakah pengguna diizinkan untuk melakukan tugas khusus ini?", Yaitu keamanan berbasis peran.
Caching : saya memproses permintaan ini, dapatkah saya mengembalikan hasil yang di-cache?
Dekorasi : bagaimana saya bisa meningkatkan permintaan untuk membuat pemrosesan hilir lebih baik?
Pemantauan Kinerja & Penggunaan : statistik apa yang bisa saya dapatkan dari permintaan dan respons?
Eksekusi : benar-benar menangani permintaan dan memberikan respons.
Mampu memisahkan tahapan yang berbeda (dan secara opsional memasukkan mereka) adalah bantuan besar dalam mengembangkan aplikasi yang terstruktur dengan baik.
Masyarakat
Ada juga sistem ramah lingkungan yang berkembang di sekitar Rack Middleware - Anda harus dapat menemukan komponen rak yang sudah dibuat sebelumnya untuk melakukan semua langkah di atas dan banyak lagi. Lihat wiki Rack GitHub untuk daftar middleware .
Apa itu Middleware?
Middleware adalah istilah mengerikan yang merujuk pada komponen perangkat lunak / pustaka yang membantu tetapi tidak terlibat langsung dalam pelaksanaan beberapa tugas. Contoh yang sangat umum adalah pencatatan, otentikasi, dan komponen pemrosesan horizontal lainnya yang umum . Ini cenderung menjadi hal-hal yang dibutuhkan semua orang di berbagai aplikasi tetapi tidak terlalu banyak orang tertarik (atau seharusnya) membangun diri mereka sendiri.
Informasi Lebih Lanjut
Komentar tentang hal itu sebagai cara untuk memfilter permintaan mungkin berasal dari episode RailsCast 151: Rack Middleware layar .
Rack middleware berevolusi dari Rack dan ada intro yang bagus di Pengantar Rack middleware .
Ada pengantar middleware di Wikipedia di sini .
sumber
Pertama-tama, Rack adalah dua hal:
Rack - Antarmuka Webserver
Dasar-dasar rak adalah konvensi sederhana. Setiap server web yang sesuai dengan rak akan selalu memanggil metode panggilan pada objek yang Anda berikan kepadanya dan melayani hasil dari metode itu. Rack menentukan dengan tepat bagaimana metode panggilan ini harus terlihat, dan apa yang harus dikembalikan. Itu rak.
Mari kita coba sederhana. Saya akan menggunakan WEBrick sebagai server yang sesuai dengan rak, tetapi salah satu dari mereka akan melakukannya. Mari kita buat aplikasi web sederhana yang mengembalikan string JSON. Untuk ini kita akan membuat file bernama config.ru. Config.ru akan secara otomatis dipanggil oleh rackup's command gem rackup yang hanya akan menjalankan konten config.ru di server-compliant-rack. Jadi mari kita tambahkan yang berikut ini ke file config.ru:
Ketika konvensi menetapkan server kami memiliki metode yang disebut panggilan yang menerima hash lingkungan dan mengembalikan array dengan bentuk [status, header, tubuh] untuk dilayani oleh server web. Mari kita coba dengan menelepon rackup. Server yang memenuhi standar rak, mungkin WEBrick atau Mongrel akan mulai dan segera menunggu permintaan untuk ditayangkan.
Mari kita uji server JSON baru kami dengan menggulung atau mengunjungi url
http://localhost:9292/hello.json
dan voila:Berhasil. Bagus! Itulah dasar untuk setiap kerangka kerja web, baik itu Rails atau Sinatra. Pada titik tertentu mereka menerapkan metode panggilan, bekerja melalui semua kode kerangka kerja, dan akhirnya mengembalikan respons dalam bentuk [status, header, tubuh] yang khas.
Di Ruby on Rails misalnya, permintaan rak hits
ActionDispatch::Routing.Mapper
kelas yang terlihat seperti ini:Jadi pada dasarnya cek Rails, tergantung pada hasv env jika ada rute yang cocok. Jika demikian ia meneruskan hash env ke aplikasi untuk menghitung respons, jika tidak maka akan segera merespons dengan 404. Jadi setiap server web yang sesuai dengan konvensi antarmuka rak, dapat melayani aplikasi Rails yang sepenuhnya meledak.
Middleware
Rack juga mendukung pembuatan lapisan middleware. Mereka pada dasarnya mencegat permintaan, melakukan sesuatu dengannya dan meneruskannya. Ini sangat berguna untuk tugas-tugas serbaguna.
Katakanlah kita ingin menambahkan logging ke server JSON kita yang juga mengukur berapa lama permintaan. Kami cukup membuat logger middleware yang melakukan ini:
Saat dibuat, ia menyimpan sendiri salinan aplikasi rak yang sebenarnya. Dalam kasus kami itu adalah contoh dari JSONServer kami. Rack secara otomatis memanggil metode panggilan pada middleware dan mengharapkan kembali
[status, headers, body]
array, seperti JSONServer kami kembali.Jadi di middleware ini, titik awal diambil, lalu panggilan aktual ke JSONServer dibuat
@app.call(env)
, kemudian logger mengeluarkan entri log dan akhirnya mengembalikan respons sebagai[@status, @headers, @body]
.Untuk membuat rackup.ru kecil kami menggunakan middleware ini, tambahkan gunakan RackLogger ke dalamnya seperti ini:
Mulai ulang server dan voila, ini mengeluarkan log pada setiap permintaan. Rak memungkinkan Anda untuk menambahkan beberapa middlewares yang dipanggil sesuai urutan penambahannya. Ini hanya cara yang bagus untuk menambahkan fungsionalitas tanpa mengubah inti dari aplikasi rak.
Rack - The Gem
Meskipun rak - pertama-tama - adalah sebuah konvensi, rak juga merupakan permata yang menyediakan fungsionalitas luar biasa. Salah satunya kami sudah menggunakan untuk server JSON kami, perintah rackup. Tapi masih ada lagi! Rak permata menyediakan sedikit aplikasi untuk banyak kasus penggunaan, seperti melayani file statis atau bahkan seluruh direktori. Mari kita lihat bagaimana kami menyajikan file sederhana, misalnya file HTML yang sangat mendasar yang terletak di htmls / index.html:
Kami mungkin ingin menayangkan file ini dari root situs web, jadi mari tambahkan yang berikut ini ke config.ru kami:
Jika kami mengunjungi,
http://localhost:9292
kami melihat file html kami dirender dengan sempurna. Itu mudah, bukan?Mari kita tambahkan seluruh direktori file javascript dengan membuat beberapa file javascript di bawah / javascripts dan menambahkan berikut ini ke config.ru:
Mulai ulang server dan kunjungi
http://localhost:9292/javascript
dan Anda akan melihat daftar semua file javascript yang dapat Anda sertakan langsung dari mana saja.sumber
Saya mengalami masalah dalam memahami Rak untuk waktu yang cukup lama. Saya hanya sepenuhnya memahaminya setelah berupaya membuat server web Ruby mini ini sendiri. Saya telah membagikan pembelajaran saya tentang Rack (dalam bentuk cerita) di sini di blog saya: http://gauravchande.com/what-is-rack-in-ruby-rails
Umpan balik lebih dari diterima.
sumber
config.ru
contoh runnable minimalLari
rackup
dan kunjungilocalhost:9292
. Outputnya adalah:Jadi jelas bahwa
Middleware
membungkus dan memanggil aplikasi utama. Oleh karena itu, ia dapat memproses lebih dulu permintaan itu, dan mempostingkan tanggapannya dengan cara apa pun.Seperti dijelaskan di: http://guides.rubyonrails.org/rails_on_rack.html#action-dispatcher-middleware-stack , Rails menggunakan Rack middlewares untuk banyak fungsionalitasnya, dan Anda dapat menambahkan Anda sendiri juga dengan
config.middleware.use
metode keluarga.Keuntungan dari penerapan fungsionalitas dalam middleware adalah Anda dapat menggunakannya kembali pada kerangka Rak apa pun, sehingga semua yang utama Ruby, dan bukan hanya Rails.
sumber
Rack middleware adalah cara untuk memfilter permintaan dan respons yang masuk ke aplikasi Anda. Komponen middleware terletak di antara klien dan server, memproses permintaan masuk dan tanggapan keluar, tapi itu lebih dari antarmuka yang dapat digunakan untuk berbicara dengan server web. Ini digunakan untuk mengelompokkan dan memesan modul, yang biasanya merupakan kelas Ruby, dan menentukan ketergantungan di antaranya. Modul rak middleware hanya harus: - memiliki konstruktor yang mengambil aplikasi berikutnya dalam stack sebagai parameter - merespons metode "panggilan", yang menggunakan hash lingkungan sebagai parameter. Nilai kembali dari panggilan ini adalah array dari: kode status, hash lingkungan dan badan respons.
sumber
Saya telah menggunakan Rack middleware untuk menyelesaikan beberapa masalah:
Itu memberi perbaikan yang cukup elegan dalam kedua kasus.
sumber
Apa itu Rack?
Rack menyediakan antarmuka minimal antara server web yang mendukung kerangka kerja Ruby dan Ruby.
Menggunakan Rack, Anda dapat menulis Aplikasi Rack.
Rack akan meneruskan hash Environment (hash, terkandung di dalam permintaan HTTP dari klien, yang terdiri dari header mirip CGI) ke Aplikasi Rack Anda yang dapat menggunakan hal-hal yang terdapat dalam hash ini untuk melakukan apa pun yang diinginkan.
Apa itu Aplikasi Rack?
Untuk menggunakan Rack, Anda harus memberikan 'aplikasi' - objek yang merespons
#call
metode dengan Environment Hash sebagai parameter (biasanya didefinisikan sebagaienv
).#call
harus mengembalikan Array dengan tepat tiga nilai:each
).Anda dapat menulis Aplikasi Rak yang mengembalikan array seperti itu - ini akan dikirim kembali ke klien Anda, oleh Rack, di dalam Respons (ini sebenarnya akan menjadi instance dari Kelas
Rack::Response
[klik untuk pergi ke dokumen]).Aplikasi Rak Sangat Sederhana:
gem install rack
config.ru
file - Rack tahu untuk mencari ini.Kami akan membuat Aplikasi Rack kecil yang mengembalikan Response (contoh
Rack::Response
) siapa Response Tubuh adalah array yang berisi String:"Hello, World!"
.Kami akan menjalankan server lokal menggunakan perintah
rackup
.Saat mengunjungi port yang relevan di browser kami, kami akan melihat "Halo, Dunia!" diberikan di viewport.
Jalankan server lokal dengan
rackup
dan kunjungi localhost: 9292 dan Anda akan melihat 'Halo, Dunia!' diberikan.Ini bukan penjelasan yang komprehensif, tetapi pada dasarnya yang terjadi di sini adalah bahwa Klien (peramban) mengirimkan Permintaan HTTP ke Rack, melalui server lokal Anda, dan Rack membuat instantiate
MessageApp
dan menjalankancall
, meneruskan Environment Hash sebagai parameter ke dalam metode ( yangenv
argumen).Rack mengambil nilai pengembalian (array) dan menggunakannya untuk membuat instance
Rack::Response
dan mengirimkannya kembali ke Klien. Peramban menggunakan sihir untuk mencetak 'Halo, Dunia!' ke layar.Kebetulan, jika Anda ingin melihat seperti apa lingkungan hash, letakkan saja di
puts env
bawahnyadef call(env)
.Minimal apa adanya, yang Anda tulis di sini adalah aplikasi Rack!
Membuat Aplikasi Rack berinteraksi dengan hash Incoming Environment
Di aplikasi Rak kecil kami, kami dapat berinteraksi dengan
env
hash (lihat di sini untuk informasi lebih lanjut tentang hash Lingkungan).Kami akan menerapkan kemampuan bagi pengguna untuk memasukkan string kueri mereka sendiri ke dalam URL, karenanya, string itu akan hadir dalam permintaan HTTP, yang dienkapsulasi sebagai nilai dalam salah satu pasangan kunci / nilai hash Lingkungan.
Aplikasi Rack kami akan mengakses string kueri dari hash Lingkungan dan mengirimkannya kembali ke klien (browser kami, dalam hal ini) melalui Badan dalam Respons.
Dari dokumen Rack pada Hash Lingkungan: "QUERY_STRING: Bagian dari URL permintaan yang mengikuti?, Jika ada. Mungkin kosong, tetapi selalu diperlukan!"
Sekarang,
rackup
dan kunjungilocalhost:9292?hello
(?hello
menjadi string kueri) dan Anda akan melihat 'halo' ditampilkan di viewport.Rack Middleware
Kami akan:
MessageSetter
,env
,MessageSetter
akan memasukkan'MESSAGE'
kunci ke hasv env, nilainya'Hello, World!'
jikaenv['QUERY_STRING']
kosong;env['QUERY_STRING']
jika tidak,@app.call(env)
-@app
menjadi aplikasi berikutnya dalam 'Stack':MessageApp
.Pertama, versi 'tangan panjang':
Dari Rack :: Builder docs kita melihatnya
Rack::Builder
mengimplementasikan DSL kecil untuk membuat aplikasi Rack secara iteratif. Ini pada dasarnya berarti bahwa Anda dapat membangun 'Stack' yang terdiri dari satu atau lebih Middlewares dan aplikasi 'level bawah' untuk dikirim. Semua permintaan melalui aplikasi tingkat bawah Anda akan diproses terlebih dahulu oleh Middleware Anda.#use
menentukan middleware untuk digunakan dalam tumpukan. Dibutuhkan middleware sebagai argumen.Rack Middleware harus:
call
metode yang menggunakan hash Environment sebagai parameter.Dalam kasus kami, 'Middleware' adalah
MessageSetter
, 'konstruktor' adalahinitialize
metode MessageSetter , 'aplikasi berikutnya' di stack adalahMessageApp
.Jadi di sini, karena apa yang
Rack::Builder
dilakukannya di bawah tenda, paraapp
argumenMessageSetter
'sinitialize
metode adalahMessageApp
.(bawa kepala Anda berkeliling di atas sebelum melanjutkan)
Oleh karena itu, setiap bagian dari Middleware pada dasarnya 'menurunkan' hash Environment yang ada ke aplikasi berikutnya dalam rantai - sehingga Anda memiliki kesempatan untuk bermutasi hash lingkungan di dalam Middleware sebelum meneruskannya ke aplikasi berikutnya di stack.
#run
mengambil argumen yang merupakan objek yang merespons#call
dan mengembalikan Respons Rak (turunan dariRack::Response
).Kesimpulan
Menggunakan
Rack::Builder
Anda dapat membangun rantai Middlewares dan permintaan apa pun ke aplikasi Anda akan diproses oleh masing-masing Middleware secara bergantian sebelum akhirnya diproses oleh bagian terakhir di stack (dalam kasus kami,MessageApp
). Ini sangat berguna karena memisahkan berbagai tahapan proses permintaan. Dalam hal 'pemisahan masalah', tidak mungkin lebih bersih!Anda dapat membuat 'pipa permintaan' yang terdiri dari beberapa Middlewares yang menangani hal-hal seperti:
(di atas poin-poin dari jawaban lain di utas ini)
Anda akan sering melihat ini dalam aplikasi profesional Sinatra. Sinatra menggunakan Rack! Lihat di sini untuk definisi apa IS Sinatra !
Sebagai catatan akhir, kami
config.ru
dapat ditulis dalam gaya tulisan tangan pendek, menghasilkan fungsionalitas yang persis sama (dan inilah yang biasanya Anda lihat):Dan untuk menunjukkan secara lebih eksplisit apa
MessageApp
yang dilakukan, inilah versi 'tangan panjang' yang secara eksplisit menunjukkan bahwa#call
menciptakan instance baruRack::Response
, dengan tiga argumen yang diperlukan.Tautan yang bermanfaat
sumber
Rack - Antarmuka dengan Web & Aplikasi Server
Rack adalah paket Ruby yang menyediakan antarmuka untuk server web untuk berkomunikasi dengan aplikasi. Sangat mudah untuk menambahkan komponen middleware antara server web dan aplikasi untuk memodifikasi cara perilaku / respons Anda. Komponen middleware berada di antara klien dan server, memproses permintaan masuk dan tanggapan keluar.
Dengan kata-kata awam, pada dasarnya ini hanya seperangkat pedoman untuk bagaimana server dan aplikasi Rails (atau aplikasi web Ruby lainnya) harus berbicara satu sama lain .
Untuk menggunakan Rack, berikan "aplikasi": objek yang merespons metode panggilan, menggunakan hash lingkungan sebagai parameter, dan mengembalikan Array dengan tiga elemen:
Untuk penjelasan lebih lanjut, Anda dapat mengikuti tautan di bawah ini.
Di rails, kami memiliki config.ru sebagai file rak, Anda dapat menjalankan file rak apa pun dengan
rackup
perintah. Dan port default untuk ini adalah9292
. Untuk menguji ini, Anda cukup menjalankanrackup
di direktori rails Anda dan lihat hasilnya. Anda juga dapat menetapkan port tempat Anda ingin menjalankannya. Perintah untuk menjalankan file rak pada port tertentu adalahsumber
Rack adalah permata yang menyediakan antarmuka sederhana untuk permintaan / respons HTTP abstrak. Rak berada di antara kerangka kerja web (Rails, Sinatra dll) dan server web (unicorn, puma) sebagai adaptor. Dari gambar di atas ini membuat server unicorn sepenuhnya independen dari mengetahui tentang rails dan rails tidak tahu tentang unicorn. Ini adalah contoh yang baik dari kopling longgar , pemisahan kekhawatiran .
Gambar di atas dari ceramah konferensi rel ini di rak https://youtu.be/3PnUV9QzB0g Saya sarankan menontonnya untuk pemahaman yang lebih dalam.
sumber