প্রতিটি Rails, Sinatra, এবং অন্যান্য রুবি ওয়েব ফ্রেমওয়ার্কের পেছনে কী হচ্ছে?
উত্তর হলো Rack, মূল কম্পোনেন্ট যা এটিকে সম্ভব করে।
কিন্তু Rack আসলে কী?
Rack হলো ফ্রেমওয়ার্ক (Rails) এবং অ্যাপ্লিকেশন সার্ভার (Puma)-এর মধ্যে একটি লেয়ার।

এটি ওই গ্লু যা তাদের কমিউনিকেশন করতে দেয়।
আমরা কেন Rack ব্যবহার করি?
আমরা Rack ব্যবহার করি কারণ এটির মাধ্যমে বিভিন্ন ফ্রেমওয়ার্ক এবং সার্ভার ইন্টারচেঞ্জেবল হয়।
তারা কম্পোনেন্টে রূপ নেয় যা আপনি প্লাগ-ইন করতে পারেন।
এর মানে আপনি Puma ব্যবহার করতে পারেন Rails, Sinatra এবং যেকোনো অন্যান্য Rack-কম্প্যাটিবল ফ্রেমওয়ার্কের সাথে। এটি মনে করুন না আপনি কোন ফ্রেমওয়ার্ক বা সার্ভার ব্যবহার করছেন যদি তারা Rack ইন্টারফেস ইমপ্লিমেন্ট করে।
Rack-এ, প্রতিটি কম্পোনেন্ট আপনার কাজ করে এবং সবাই খুশি!
Rack Middleware কী?
Rack প্রতিটি ওয়েব রিকোয়েস্ট এবং রেসপন্সের মাঝপথে থাকে।
ফলস্বরূপ, এটি একটি গার্ডিয়ান হিসেবে কাজ করতে পারে, অনিচ্ছাকৃত রিকোয়েস্ট ডেনাই করে, বা একটি ইতিহাসবিদ হিসেবে, ধীর রেসপন্স ট্র্যাক রাখতে পারে।
এইটিই Rack middleware!
ছোট রুবি প্রোগ্রাম যা রিকোয়েস্ট-রেসপন্স সাইকেলের অংশ হিসেবে কল হয় এবং সেটির সাথে কিছু করার সুযোগ পায়।
এটি কী ধরনের কাজের জন্য ব্যবহার হয়?
- লগিং
- সেশন
- প্রোফাইলিং (একটি রিকোয়েস্ট কতক্ষণে পূর্ণ হয় সেটি জানতে)
- ক্যাশিং
- সিকিউরিটি (IP অ্যাড্রেস অনুযায়ী রিকোয়েস্ট ডেনাই করা, বা রিকোয়েস্ট সংখ্যা লিমিট করা)
- স্ট্যাটিক ফাইল সার্ভ করা (css, js, png…)
এই সব খুব উপকারী এবং রেলস মিডলওয়্যার ভালোভাবে ব্যবহার করে তার কিছু ফাংশনালিটি ইমপ্লিমেন্ট করতে।
আপনি একটি রেলস প্রজেক্টের ভিতরে rake middleware দিয়ে মিডলওয়্যারের লিস্ট দেখতে পারেন।
এখন, আমি যে Rack ইন্টারফেস-এর কথা বলেছিলাম।
এটি কেমন দেখায়?
আপনাকে একটি উদাহরণ দিয়ে দেখাই…
আপনার নিজস্ব Rack অ্যাপ্লিকেশন কীভাবে লিখবেন
আপনি 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
এই কোড পোর্ট ৮০৮০-এ একটি সার্ভার 스타র্ট করবে (ট্রাই করুন!)।
যে অ্যারেটি রিটার্ন হচ্ছে সেটি কী?
- HTTP স্ট্যাটাস কোড (200)
- HTTP হেডার্স (“Content-Type”)
- কন্টেন্ট (“Hello from Rack”)
আপনি যদি রিকোয়েস্ট ডিটেইলস অ্যাক্সেস করতে চান তবে env আর্গুমেন্ট ব্যবহার করতে পারেন।
এভাবেই:
req = Rack::Request.new(env)
এই মেথডগুলো উপলব্ধ:
- path_info (/articles/1)
- ip (ইউজারের)
- user_agent (Chrome, Firefox, Safari…)
- request_method (get / post)
- body (কন্টেন্ট)
- media_type (plain, 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 ট্রাই করুন, লোকালহোস্টের IPv6 ভার্সন।
Rack Middleware কীভাবে লিখবেন ও ব্যবহার করবেন
এখন:
আপনি অ্যাপ্লিকেশন এবং মিডলওয়্যারকে কীভাবে চেইন করবেন যাতে সেগুলো একসাথে কাজ করে?
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
এই উদাহরণে আমাদের দুটি Rack অ্যাপ্লিকেশন আছে:
- 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 সম্পর্কে শিখেছেন, वह ইন্টারফেস যা রুবি ওয়েব ফ্রেমওয়ার্ক এবং সার্ভারের মধ্যে ইন্টারঅ্যাকশন চালাচ্ছে। আপনি নিজের Rack অ্যাপ্লিকেশন লিখে শিখেছেন এটি কীভাবে কাজ করে।
আপনার যেকোনো প্রশ্ন বা ফিডব্যাক থাকলে নিচে কমেন্ট করুন।
পড়ার জন্য ধন্যবাদ!