เกิดอะไรขึ้นเบื้องหลังของทุก Rails, Sinatra และเฟรมเวิร์กเว็บ Ruby อื่นๆ
คำตอบคือ Rack ซึ่งเป็นองค์ประกอบหลักที่ทำให้สิ่งนี้เป็นไปได้
แต่แร็คคืออะไรกันแน่?
Rack เป็นเลเยอร์ระหว่างเฟรมเวิร์ก (Rails) และแอพพลิเคชั่นเซิร์ฟเวอร์ (Puma)
เป็นกาวที่ช่วยให้สื่อสารได้
เหตุใดเราจึงต้องใช้แร็ค
เราใช้แร็คเพราะทำให้เฟรมเวิร์กและเซิร์ฟเวอร์ต่างๆ สามารถใช้แทนกันได้
สิ่งเหล่านี้กลายเป็นส่วนประกอบที่คุณสามารถเสียบเข้าไปได้ .
ซึ่งหมายความว่าคุณสามารถใช้ Puma กับ Rails, Sinatra และเฟรมเวิร์กอื่นๆ ที่เข้ากันได้กับแร็ค ไม่ว่าคุณจะใช้เฟรมเวิร์กหรือเซิร์ฟเวอร์ใด หากพวกเขาใช้อินเทอร์เฟซของแร็ค .
ด้วย Rack ทุกองค์ประกอบทำงานและทุกคนก็มีความสุข!
Rack Middleware คืออะไร
แร็คตั้งอยู่ตรงกลางของทุกคำขอและการตอบสนองของเว็บ
ด้วยเหตุนี้ จึงสามารถทำหน้าที่เป็นผู้ปกครอง โดยการปฏิเสธการเข้าถึงคำขอที่ไม่ต้องการ หรือสามารถทำหน้าที่เป็นนักประวัติศาสตร์โดยการติดตามการตอบสนองที่ช้า
นั่นคือสิ่งที่แร็คมิดเดิลแวร์ คือ!
โปรแกรม Ruby ขนาดเล็กที่ถูกเรียกใช้โดยเป็นส่วนหนึ่งของวงจรการตอบกลับคำขอและมีโอกาสทำบางสิ่งกับมัน
สิ่งนี้ใช้สำหรับอะไร
- การบันทึก
- เซสชัน
- การทำโปรไฟล์ (ค้นหาว่าคำขอใช้เวลานานเท่าใดจึงจะเสร็จสมบูรณ์)
- แคช
- ความปลอดภัย (ปฏิเสธคำขอตามที่อยู่ IP หรือจำกัด # คำขอ)
- แสดงไฟล์สแตติก (css, js, png…)
สิ่งเหล่านี้มีประโยชน์มาก &Rails ใช้ประโยชน์จากมิดเดิลแวร์เพื่อนำฟังก์ชันบางอย่างไปใช้งาน .
คุณสามารถดูรายการมิดเดิลแวร์ด้วย rake middleware
ภายในโครงการ Rails
ตอนนี้ อินเทอร์เฟซของชั้นวาง ฉันได้กล่าวไว้ก่อนหน้านี้
ลักษณะเป็นอย่างไร?
ผมขอแสดงให้คุณเห็นตัวอย่าง…
วิธีการเขียนแอปพลิเคชันแร็คของคุณเอง
คุณสามารถเรียนรู้วิธีการทำงานของ Rack โดยการเขียนใบสมัครของคุณเอง
มาทำสิ่งนี้กันเถอะ!
แอปพลิเคชัน Rack เป็นคลาสที่มีวิธีเดียว:call
.
หน้าตาเป็นแบบนี้ :
require 'rack' handler = Rack::Handler::Thin class RackApp def call(env) [200, {"Content-Type" => "text/plain"}, "Hello from Rack"] end end handler.run RackApp.new
รหัสนี้จะเริ่มต้นเซิร์ฟเวอร์บนพอร์ต 8080 (ลองเลย! )
อาร์เรย์นี้ถูกส่งคืนอะไร
- รหัสสถานะ HTTP (200)
- ส่วนหัว HTTP (“ประเภทเนื้อหา”)
- เนื้อหา (“สวัสดีจากแร็ค”)
หากคุณต้องการเข้าถึงรายละเอียดคำขอ คุณสามารถใช้ env
อาร์กิวเมนต์
ถูกใจสิ่งนี้ :
req = Rack::Request.new(env)
วิธีการเหล่านี้ใช้ได้ :
- path_info (/articles/1)
- ip (ของผู้ใช้)
- user_agent (Chrome, Firefox, Safari…)
- request_method (รับ / โพสต์)
- เนื้อหา (เนื้อหา)
- media_type (ธรรมดา, json, html)
คุณสามารถใช้ข้อมูลนี้เพื่อ สร้างแอปพลิเคชัน Rack ของคุณ .
ตัวอย่างเช่น เราสามารถปฏิเสธการเข้าถึงเนื้อหาของเราได้หากที่อยู่ IP คือ 5.5.5.5
.
นี่คือรหัส :
require 'rack' handler = Rack::Handler::Thin class RackApp def call(env) req = Rack::Request.new(env) if req.ip == "5.5.5.5" [403, {}, ""] else [200, {"Content-Type" => "text/plain"}, "Hello from Rack"] end end end handler.run RackApp.new
คุณสามารถเปลี่ยนที่อยู่เป็น 127.0.0.1
ถ้าต้องการเห็นผล
หากไม่ได้ผล ให้ลอง ::1
, localhost เวอร์ชัน IPv6
วิธีการเขียนและใช้แร็คมิดเดิลแวร์
ตอนนี้:
คุณเชื่อมโยงแอปพลิเคชันและมิดเดิลแวร์เพื่อให้ทำงานร่วมกันได้อย่างไร
การใช้ Rack::Builder
.
วิธีทำความเข้าใจที่ดีที่สุดคือการยกตัวอย่าง
นี่คือแอป Rack ของเรา :
require 'rack' handler = Rack::Handler::Thin class RackApp def call(env) req = Rack::Request.new(env) [200, {"Content-Type" => "text/plain"}, "Hello from Rack - #{req.ip}"] end end
นี่คือมิดเดิลแวร์ :
class FilterLocalHost def initialize(app) @app = app end def call(env) req = Rack::Request.new(env) if req.ip == "127.0.0.1" || req.ip == "::1" [403, {}, ""] else @app.call(env) end end end
นี่คือวิธีที่เรารวมมันเข้าด้วยกัน :
app = Rack::Builder.new do |builder| builder.use FilterLocalHost builder.run RackApp.new end handler.run app
ในตัวอย่างนี้ เรามีแอปพลิเคชันแร็คสองตัว:
- หนึ่งรายการสำหรับการตรวจสอบ IP (
FilterLocalHost
) - หนึ่งสำหรับแอปพลิเคชันเพื่อส่งเนื้อหา (HTML, JSON ฯลฯ)
ขอให้สังเกตว่า @app.call(env)
นั่นคือสิ่งที่ทำให้ FilterLocalHost
มิดเดิลแวร์
สองสิ่งนี้เกิดขึ้นได้ :
- เราตอบกลับซึ่งจะหยุดห่วงโซ่มิดเดิลแวร์
- เราส่งคำขอพร้อมกับ
@app.call(env)
ไปยังมิดเดิลแวร์ตัวถัดไป หรือตัวแอปเอง
ภายในส่วนใดๆ ของแอป Rack รวมถึงมิดเดิลแวร์ คุณสามารถเปลี่ยนการตอบสนองได้
ตัวอย่าง :
class UpcaseAll def initialize(app) @app = app end def call(env) status, headers, response = @app.call(env) response.upcase! [status, headers, response] end end
นั่นเป็นวิธีที่ Rack ทำงาน 🙂
สรุป
คุณได้เรียนรู้เกี่ยวกับ Rack ซึ่งเป็นอินเทอร์เฟซที่ขับเคลื่อนการโต้ตอบระหว่างเฟรมเวิร์กเว็บและเซิร์ฟเวอร์ของ Ruby คุณยังได้เรียนรู้วิธีเขียนแอปพลิเคชัน Rack ของคุณเองเพื่อให้เข้าใจวิธีการทำงาน
หากคุณมีคำถามหรือข้อเสนอแนะโปรดแสดงความคิดเห็นด้านล่าง
ขอบคุณสำหรับการอ่าน!