Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เข้าใจ Rack: โครงสร้างหลักของ Ruby Web Frameworks

เกิดอะไรขึ้นเบื้องหลังของ Rails, Sinatra และ Ruby web frameworks อื่นๆ ทุกตัว?

คำตอบคือ Rack, key component ที่ทำให้เป็นไปได้

แต Rack คืออะไรแน่?

Rack เป็น layer ระหว่าง framework (Rails) และ application server (Puma)

เข้าใจ Rack: โครงสร้างหลักของ Ruby Web Frameworks

มันคือกาวที่ให้พวกมัน communicate ได้

ทำไมเราใช้ Rack?

เราใช้ Rack เพราะมันทำให้ frameworks และ servers ต่างๆ สลับกันได้

พวกมันกลายเป็น components ที่ plug-in ได้

นี่หมายถึงคุณใช้ Puma กับ Rails, Sinatra และ Rack-compatible frameworks อื่นๆ ได้ ไม่สำคัญ framework หรือ server ไหน ถ้าพวกมัน implement Rack interface

ด้วย Rack ทุก component ทำหน้าที่ของมัน และทุกคนมีความสุข!

Rack Middleware คืออะไร?

Rack นั่งกลางของทุก web request และ response

ผลคือ มัน act as guardian โดย deny access unwanted requests หรือ act as historian โดย track slow responses

นั่นคือ Rack middleware!

Ruby programs เล็กๆ ที่ถูกเรียกเป็นส่วนหนึ่งของ request-response cycle และได้โอกาสทำอะไรกับมัน

ใช้ทำอะไรบ้าง?

  • Logging
  • Sessions
  • Profiling (หาว่า request ใช้เวลานานแค่ไหน)
  • Caching
  • Security (deny requests by IP, หรือ limit # requests)
  • Serving static files (css, js, png…)

สิ่งเหล่านี้ useful มาก และ Rails ใช้ middleware ทำให้ฟีเจอร์บางอย่างทำงานได้

คุณดูรายการ middleware ด้วย rake middleware ใน Rails project

ตอนนี้ Rack interface ที่กล่าวไป

มัน长什么?

มา show ด้วยตัวอย่าง…

วิธีเขียน Rack Application เอง

คุณเรียนรู้ Rack ทำงานอย่างไรโดยเขียน application เอง

มาทำกัน!

Rack application คือคลาสที่มีหนึ่งเมธอด: 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

โค้ดนี้จะเริ่ม server บน port 8080 (ลองดู!)

อาร์เรย์ที่คืนคืออะไร?

  • HTTP status code (200)
  • HTTP headers ("Content-Type")
  • Contents ("Hello from Rack")

หากอยากเข้าถึง request details ใช้ argument env

แบบนี้:

req = Rack::Request.new(env)

เมธอดเหล่านี้พร้อมใช้:

  • path_info (/articles/1)
  • ip (ของ user)
  • user_agent (Chrome, Firefox, Safari…)
  • request_method (get / post)
  • body (contents)
  • media_type (plain, json, html)

คุณใช้ข้อมูลนี้ สร้าง Rack application ของคุณ

เช่น เรา deny access เนื้อหา หาก IP address เป็น 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

คุณเปลี่ยน address เป็น 127.0.0.1 หากอยากเห็น effect

หากไม่ได้ ลอง ::1 IPv6 version ของ localhost

วิธีเขียนและใช้ Rack Middleware

ตอนนี้:

คุณ chain application และ middleware ให้ทำงานร่วมกันอย่างไร?

ใช้ Rack::Builder

วิธีเข้าใจดีที่สุดคือตัวอย่าง

นี่คือ Rack app:

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

นี่คือ middleware:

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

ในตัวอย่างนี้ มีสอง Rack applications:

  • หนึ่งสำหรับ IP check (FilterLocalHost)
  • หนึ่งสำหรับ application เองส่ง content (HTML, JSON ฯลฯ)

สังเกต @app.call(env) นั่นคือสิ่งที่ทำให้ FilterLocalHost เป็น middleware

หนึ่งในสองสิ่งเกิดขึ้น:

  • เราคืน response ซึ่งหยุด middleware chain
  • เราส่ง request ต่อด้วย @app.call(env) ไป middleware ถัดไป หรือ app เอง

ภายในทุกส่วนของ Rack app รวม middleware คุณเปลี่ยน response ได้

ตัวอย่าง:

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 interface ที่ขับเคลื่อน interaction ระหว่าง Ruby web frameworks และ servers คุณยังเรียนรู้วิธีเขียน Rack application เองเพื่อเข้าใจการทำงาน

หากมีคำถามหรือ feedback ยินดีรับฟังใน comments ด้านล่าง

ขอบคุณที่อ่าน!