কম্পিউটার টিউটোরিয়াল

রুবি অন রেইলসে API ডেভেলপমেন্টে দক্ষতা অর্জন

আজকাল API (অ্যাপ্লিকেশন প্রোগ্রামিং ইন্টারফেস) এর ওপর নির্ভর করা একটি সাধারণ অভ্যাস। শুধু বড় সার্ভিসগুলো যেমন ফেসবুক ও টুইটারই নয়—ক্লায়েন্ট-সাইড ফ্রেমওয়ার্কগুলো যেমন React, Angular, এবং অন্য অনেকের প্রসারের কারণে API খুব জনপ্রিয়। রুবি অন রেইলস এই ট্রেন্ডের পেছনে নয়, এবং লেটেস্ট ভার্সনে একটি নতুন ফিচার এসেছে যা API-অনলি অ্যাপ্লিকেশন তৈরি করার অনুমতি দেয়।

প্রাথমিকভাবে এই ফাংশনালিটি একটি আলাদা জেমে প্যাক করা ছিল যার নাম rails-api, কিন্তু রেইলস ৫ রিলিজ হওয়ার পর থেকে এটি ফ্রেমওয়ার্কের কোরের অংশ হয়ে গেছে। এই ফিচার(ActionCable-এর পাশাপাশি) সম্ভবত সবচেয়ে বেশি প্রত্যাশিত ছিল, এবং আজ আমরা এ этом নিয়ে আলোচনা করব।

এই নিবন্ধে API-অনলি রেইলস অ্যাপ্লিকেশন তৈরি করা, রাউট ও কন্ট্রোলার স্ট্রাকচার করা, JSON ফরম্যাটে রেসপন্স করা, সিরিয়ালাইজার যোগ করা, এবং CORS (Cross-Origin Resource Sharing) সেট আপ করা কভার করা হয়েছে। আপনি API সিকিউর করতে এবং অপদমৃষ্টি থেকে রক্ষা করার কিছু অপশনও জানবেন।

এই নিবন্ধের সোর্স গিটহাবে পাওয়া যাবে।

API-অনলি অ্যাপ্লিকেশন তৈরি করা

শুরু করতে নিচের কমান্ড চালান:

এটি RailsApiDemo নামে একটি নতুন API-অনলি রেইলস অ্যাপ্লিকেশন তৈরি করবে। মনে রাখবেন যে --api অপশন সাপোর্ট রেইলস ৫-এ যোগ হয়েছে, তাই নিশ্চিত হন যে আপনার এই বা নতুন ভার্সন ইনস্টল করা আছে।

Gemfile খুলুন এবং লক্ষ্য করুন যে এটি সাধারণত থেকে অনেক ছোট: coffee-rails, turbolinks, এবং sass-rails এর মত জেমগুলো নেই।

config/application.rb ফাইলে একটি নতুন লাইন রয়েছে:

এর মানে রেইলস ছোট সেট মিডলওয়্যার লোড করবে: উদাহরণস্বরূপ, কুকি ও সেশন সাপোর্ট নেই।而且, যদি আপনি স্ক্যাফফোল্ড জেনারেট করতে চান, ভিউ ও অ্যাসেট তৈরি হবে না। আসলে, যদি আপনি views/layouts ডিরেক্টরি চেক করেন, তো application.html.erb ফাইলটি মিসিং পাবেন।

একটি আরো গুরুত্বপূর্ণ পার্থক্য হলো ApplicationController ActionController::API- থেকে ইনহেরিট করে, ActionController::Base-এর পরিবর্তে।

এটুকুই—সব মিলিয়ে এটি একই বেসিক রেইলস অ্যাপ্লিকেশন যা আপনি অনেকবার দেখেছেন। এখন কয়েকটি মডেল যোগ করি যাতে আমাদের কাজ করার কিছু থাকে:

এখানে কিছু ফ্যান্সি নেই: একটি পোস্ট যার টাইটেল এবং বডি থাকে, এবং এটি একজন ইউজারের অন্তর্গত।

সঠিক অ্যাসোসিয়েশন সেট আপ করুন এবং কিছু সিম্পল ভ্যালিডেশন চেক যোগ করুন:

models/user.rb

models/post.rb

চমৎকার! পরবর্তী ধাপ হলো নতুন তৈরি টেবিলগুলোতে কিছু স্যাম্পল রেকর্ড লোড করা।

ডেমো ডেটা লোড করা

কিছু ডেটা লোড করার সবচেয়ে সহজ পথ হলো db ডিরেক্টরির ভিতরে seeds.rb ফাইল ব্যবহার করা। কিন্তু আমি অলস (অনেক প্রোগ্রামারের মত) এবং কোনো স্যাম্পল কন্টেন্ট চিন্তা করতে চাই না। তাই কেন না faker জেমের সুবিধা নিই যা వివিধ রকম র‍্যান্ডম ডেটা তৈরি করতে পারে: নাম, ইমেইল, হিপস্টার শব্দ, "lorem ipsum" টেক্সট, এবং আরও অনেক কিছু।

Gemfile

জেম ইনস্টল করুন:

এখন seeds.rb মডিফাই করুন:

db/seeds.rb

শেষে, আপনার ডেটা লোড করুন:

JSON-এ রেসপন্স করা

এখন, অবশ্যই, আমাদের API তৈরি করার জন্য কিছু রাউট ও কন্ট্রোলার লাগবে। API-এর রাউটগুলো api/ পাথের নিচে नेস্ট করা একটি সাধারণ অভ্যাস। ডেভেলপাররা সাধারণত API-এর ভার্সনও পাথে দেয়, যেমন api/v1/। পরে যদি কিছু ব্রেকিং চেঞ্জ আনতে হয়, তবে আপনি সহজেই একটি নতুন নেমস্পেস (v2) এবং আলাদা কন্ট্রোলার তৈরি করতে পারবেন।

আপনার রাউটগুলো এভাবে দেখাতে পারে:

config/routes.rb

এটি নিচের মতো রাউট জেনারেট করবে:

আপনি namespace-এর পরিবর্তে scope মেথডও ব্যবহার করতে পারেন, তবে তখন ডিফল্টরূপে এটি UsersController এবং PostsController খুঁজবে controllers ডিরেক্টরিতে, controllers/api/v1-এ না, তাই সতর্ক থাকুন।

controllers ডিরেক্টরির ভিতরে api ফোল্ডার তৈরি করুন এবং তার ভিতরে নেস্টেড ডিরেক্টরি v1। এতে আপনার কন্ট্রোলারগুলো পপুলেট করুন:

controllers/api/v1/users_controller.rb

controllers/api/v1/posts_controller.rb

নোট করুন, কন্ট্রোলারের ফাইল শুধু api/v1 পাথের নিচে নেস্ট করাই কাফি নয়, ক্লাসটিকেও Api এবং V1 মডিউলের ভিতরে নেমস্পেস করতে হয়।

পরবর্তী প্রশ্ন হলো JSON-ফরম্যাটে ডেটা কীভাবে প্রপারলি রেসপন্স করতে হয়? এই নিবন্ধে আমরা দুটি সমাধান ট্রাই করব: jBuilder এবং active_model_serializers জেম। তাই পরবর্তী সেকশনে যাওয়ার আগে এগুলো Gemfile-এ যোগ করুন:

Gemfile

তারপর চালান:

jBuilder জেম ব্যবহার করা

jBuilder রেইলস টিম দ্বারা রক্ষণাবেক্ষিত একটি জনপ্রিয় জেম যা একটি সিম্পল DSL (ডোমেন-স্পেসিফিক ল্যাঙ্গুয়েজ) প্রদান করে যা আপনাকে আপনার ভিউতে JSON স্ট্রাকচার ডিফাইন করতে দেয়।

মান লেন আমরা চাই যখন ইউজার index অ্যাকশন হিট করবে তখন সব পোস্ট দেখানো হোক:

controllers/api/v1/posts_controller.rb

আপনার করণীয় হলো সংশ্লিষ্ট অ্যাকশনের নামানুসারে ভিউ তৈরি করা যার এক্সটেনশন হবে .json.jbuilder। লক্ষ্য করুন যে ভিউটিও api/v1 পাথের নিচে রাখতে হবে:

views/api/v1/posts/index.json.jbuilder

json.array! @posts অ্যারেটি ট্রাভার্স করে। json.id, json.title এবং json.body সংশ্লিষ্ট নামের কি জেনারেট করে আর্গুমেন্টকে ভ্যালু হিসেবে সেট করে। https://localhost:3000/api/v1/posts.json-এ নেভিগেট করলে আপনি নিচের আউটপুটের মতো কিছু দেখবেন:

যদি আমরা প্রতিটি পোস্টের জন্য লেখকও দেখাতে চাই? সেটা সহজ:

আউটপুট পরিবর্তন হবে:

.jbuilder ফাইলগুলোর কন্টেন্ট সাধারণ রুবি কোড, তাই আপনি সকল বেসিক অপারেশন সাধারণভাবে ব্যবহার করতে পারেন।

নোট করুন jBuilder পার্শিয়াল সাপোর্ট করে সাধারণ রেইলস ভিউর মতো, তাই আপনি বলতে পারেন:

তারপর views/api/v1/posts/_post.json.jbuilder ফাইল তৈরি করুন নিচের কন্টেন্টসহ:

তো আপনি দেখছেন, jBuilder সহজ এবং সুবিধাজনক। কিন্তু বিকল্প হিসেবে, আপনি সিরিয়ালাইজারও ব্যবহার করতে পারেন, তাই পরবর্তী সেকশনে সেটি আলোচনা করি।

সিরিয়ালাইজার ব্যবহার করা

rails_model_serializers জেমটি তাদের তৈরি করেছেন যারা αρχে rails-api ম্যানেজ করত। ডকুমেন্টেশনে বলা হয়েছে, rails_model_serializers আপনার JSON জেনারেশনে কনভেনশন ওভার কনফিগারেশন আনে। মূলত, আপনি ডিফাইন করেন সিরিয়ালাইজেশন (অর্থাৎ JSON জেনারেশন) এর সময় কোন ফিল্ডগুলো ব্যবহার করা উচিত।

আমাদের প্রথম সিরিয়ালাইজার:

serializers/post_serializer.rb

এখানে আমরা বলছি এই সব ফিল্ড রেজাল্টিং JSON-এ থাকবে। এখন to_json এবং as_json মেথডগুলো পোস্টের ওপর কল করলে এই কনফিগারেশন ব্যবহার করে প্রপার কন্টেন্ট রিটার্ন করবে।

এটি একশনে দেখতে, index অ্যাকশন এভাবে মডিফাই করুন:

controllers/api/v1/posts_controller.rb

as_json অটোমেটিক্যালি @posts অবজেক্টের ওপর কল হবে।

ইউজারদের বিষয়ে কী? সিরিয়ালাইজার আপনাকে রিলেশন ইন্ডিকেট করতে দেয়, মডেলের মত। আরও, সিরিয়ালাইজার নেস্টেডও হতে পারে:

serializers/post_serializer.rb

এখন পোস্ট সিরিয়ালাইজ করলে সেটি অটোমেটিক্যালি নেস্টেড user কি থাকবে তার id এবং name সহ। যদি পরে আপনি ইউজারের জন্য আলাদা একটি সিরিয়ালাইজার তৈরি করেন :id অ্যাট্রিবিউট বাদ দিয়ে:

serializers/post_serializer.rb

তবে @user.as_json ইউজারের id রিটার্ন করবে না। তবে @post.as_json ইউজারের নাম এবং id দুটোই রিটার্ন করবে, তাই মনে রাখবেন।

API সিকিউর করা

অনেক কেসে, আমরা চাই না যে কেউ API ব্যবহার করে যেকোনো অ্যাকশন পারফর্ম করতে পারে। তাই একটি সিম্পল সিকিউরিটি চেক দেখিয়ে ইউজারদের বাধ্য করি তাদের টোকেন পাঠাতে পোস্ট তৈরি ও ডিলিট করার সময়।

টোকেনের লাইফস্প্যান আনলিমিটেড হবে এবং ইউজার রেজিস্ট্রেশনের সময় তৈরি হবে। প্রথমে users টেবিলে একটি নতুন token কলাম যোগ করুন:

এই ইনডেক্স ইউনিকনেস গ্যারান্টি করবে কারণ একই টোকেনের দুজন ইউজার থাকতে পারবে না:

db/migrate/xyz_add_token_to_users.rb

মাইগ্রেশন প্রয়োগ করুন:

এখন before_save কলব্যাক যোগ করুন:

models/user.rb

generate_token প্রাইভেট মেথড একটি টোকেন এন্ডলেস সাইকেলে তৈরি করবে এবং চেক করবে সেটি ইউনিক কিনা। যতক্ষণ একটি ইউনিক টোকেন পাওয়া যাবে, ততক্ষণ রিটার্ন করবে:

models/user.rb

আপনি অন্য অ্যালগরিদমও ব্যবহার করতে পারেন টোকেন জেনারেট করতে, উদাহরণস্বরূপ ইউজারের নামের MD5 হ্যাশ এবং কিছু সোল্ট বেস করে।

ইউজার রেজিস্ট্রেশন

অবশ্যই, আমাদের ইউজার রেজিস্ট্রেশনও অনুমতি দিতে হবে, কারণ অন্যথায় তারা তাদের টোকেন পাবে না। আমি আমাদের অ্যাপ্লিকেশনে কোনো HTML ভিউ আনার চাই না, তাই বরং একটি নতুন API মেথড যোগ করি:

controllers/api/v1/users_controller.rb

মেনিংফুল HTTP স্ট্যাটাস কোড রিটার্ন করা ভালো আইডিয়া যাতে ডেভেলপাররা বুঝতে পারে ঠিক কী হচ্ছে। এখন আপনি হয় ইউজারদের জন্য একটি নতুন সিরিয়ালাইজার দিতে পারেন বা .json.jbuilder ফাইল ব্যবহার করতে পারেন। আমি দ্বিতীয় অপশন পছন্দ করি (তাই render মেথডে :json অপশন পাস করিনি), কিন্তু আপনি যেকোনো একটি বেছে নিতে পারেন। লক্ষ্য করুন, টোকেন সবসময় সিরিয়ালাইজ করা উচিত নয়, উদাহরণস্বরূপ সব ইউজার লিস্ট রিটার্ন করার সময়—এটি সুরক্ষিত রাখা উচিত!

views/api/v1/users/create.json.jbuilder

পরবর্তী ধাপ হলো সব ঠিক কাজ করছে কিনা টেস্ট করা। আপনি হয় curl কমান্ড ব্যবহার করতে পারেন বা কিছু রুবি কোড লিখতে পারেন। যেহেতু এই নিবন্ধ রুবি নিয়ে, আমি কোডিং অপশন বেছে নিচ্ছি।

ইউজার রেজিস্ট্রেশন টেস্ট করা

HTTP রিকোয়েস্ট করার জন্য আমরা Faraday জেম ব্যবহার করব, যা বহু অ্যাডাপ্টারের ওপর একটি কমন ইন্টারফেস দেয় (ডিফল্ট হলো Net::HTTP)। একটি আলাদা রুবি ফাইল তৈরি করুন, Faraday ইনক্লুড করুন, এবং ক্লায়েন্ট সেট আপ করুন:

api_client.rb

এই সকল অপশন খুবই স্ব-ব্যাখ্যামূলক: আমরা ডিফল্ট অ্যাডাপ্টার বেছে নিচ্ছি, রিকোয়েস্ট URL সেট করছি https://localhost:300/api/v1/users-এ, কন্টেন্ট টাইপ application/json-এ পরিবর্তন করছি, এবং আমাদের রিকোয়েস্টের বডি দিচ্ছি।

সার্ভারের রেসপন্স JSON থাকবে, তাই পার্স করার জন্য আমি Oj জেম ব্যবহার করব:

api_client.rb

পার্স করা রেসপন্সের পাশাপাশি, ডিবাগিংয়ের জন্য স্ট্যাটাস কোডও দেখাচ্ছি।

এখন এই স্ক্রিপ্ট চালান:

এবং পাওয়া টোকেন কোথাও সংরক্ষণ করুন—পরবর্তী সেকশনে ব্যবহার করব।

টোকেন দিয়ে প্রমাণীকরণ

টোকেন প্রমাণীকরণ বাধ্যতামূলক করতে authenticate_or_request_with_http_token মেথড ব্যবহার করা যায়। এটি ActionController::HttpAuthentication::Token::ControllerMethods মডিউলের অংশ, তাই এটিকে ইনক্লুড করতে ভুলবেন না:

controllers/api/v1/posts_controller.rb

একটি নতুন before_action এবং সংশ্লিষ্ট মেথড যোগ করুন:

controllers/api/v1/posts_controller.rb

এখন যদি টোকেন সেট না থাকে বা সেই টোকেনের সাথে কোনো ইউজার না পাওয়া যায়, 401 এরর রিটার্ন হবে, অ্যাকশন এক্সিকিউট হওয়া বন্ধ করবে।

লক্ষ্য করুন যে ক্লায়েন্ট ও সার্ভারের যোগাযোগ অবশ্যই HTTPS-ওয়ার হবে, কারণ অন্যথায় টোকেন সহজে স্পুফ করা যাবে। অবশ্য, প্রদত্ত সমাধান আidyllic নয়, এবং অনেক কেসে OAuth 2 প্রোটোকল ব্যবহার করা পছন্দনীয়। এই ফিচার সাপোর্ট করার প্রক্রিয়া খুব সহজ করার জন্য কমপক্ষে দুটি জেম রয়েছে: Doorkeeper এবং oPRO।

পোস্ট তৈরি করা

আমাদের প্রমাণীকরণ একশনে দেখতে, PostsController-এ create অ্যাকশন যোগ করুন:

controllers/api/v1/posts_controller.rb

এখানে আমরা সিরিয়ালাইজারের সুবিধা নিচ্ছি প্রপার JSON দেখাতে। @user ইতিমধ্যে before_action-এ সেট হয়েছে।

এখন এই সিম্পল কোড দিয়ে সব টেস্ট করুন:

api_client.rb

token_auth-এ পাস করা আর্গুমেন্টটি রেজিস্ট্রেশনের সময় পাওয়া টোকেন দিয়ে রিপ্লেস করুন, এবং স্ক্রিপ্ট চালান।

পোস্ট ডিলিট করা

পোস্ট ডিলিশন একইভাবে হয়। destroy অ্যাকশন যোগ করুন:

controllers/api/v1/posts_controller.rb

আমরা শুধু ইউজারদের তাদের নিজের পোস্ট ডিলিট করার অনুমতি দিচ্ছি। পোস্ট সফলভাবে মুছে ফেলা হলে 204 স্ট্যাটাস কোড (নো কন্টেন্ট) রিটার্ন হবে। বিকল্পভাবে, আপনি ডিলিট হওয়া পোস্টের id-ও রেসপন্স দিতে পারেন কারণ সেটি মেমরি থেকে এখনও আ্যাকসেসIBLE থাকবে।

এই নতুন ফিচার টেস্ট করার কোড:

api_client.rb

পোস্টের id-কে আপনার কাজের সংখ্যা দিয়ে রিপ্লেস করুন।

CORS সেট আপ করা

আপনি যদি চান অন্যান্য ওয়েব সার্ভিস আপনার API অ্যাক্সেস করতে পারে (ক্লায়েন্ট-সাইড থেকে), তবে CORS (Cross-Origin Resource Sharing) প্রপারলি সেট আপ করা উচিত। মূলত, CORS ওয়েব অ্যাপ্লিকেশনকে থার্ড-পার্টি সার্ভিসে AJAX রিকোয়েস্ট পাঠাতে দেয়। خوشবিশেষ, rack-cors নামে একটি জেম আছে যা আমাদের সহজে সব সেট আপ করতে দেয়। Gemfile-এ এড করুন:

Gemfile

ইনস্টল করুন:

তারপর config/initializers/cors.rb ফাইলে কনফিগারেশন দিন। আসলে এই ফাইলটি ইতিমধ্যে তৈরি করা থাকে এবং একটি ইউজেজ উদাহরণ থাকে। জেমের পেজেও বেশ ডিটেইলড ডকুমেন্টেশন পাওয়া যায়।

নিচের কনফিগারেশন, উদাহরণস্বরূপ, কারোকে যেকোনো মেথড ব্যবহার করে আপনার API অ্যাক্সেস করতে দেবে:

config/initializers/cors.rb

অপদমৃষ্টি প্রতিরোধ করা

এই গাইডে আমি যে শেষ জিনিসটি উল্লেখ করব সেটি হলো আপনার API কীভাবে অপদমৃষ্টি এবং ডিনায়াল অফ সার্ভিস আটাক থেকে রক্ষা করতে হয়। rack-attack নামে একটি ভালো জেম আছে (Kickstarter-এর লোকদের তৈরি) যা আপনাকে ক্লায়েন্ট ব্ল্যাকলিস্ট বা হোয়াইটলিস্ট করতে দেয়, সার্ভারকে রিকোয়েস্ট দিয়ে ফ্লাড করা থেকে রোধ করে, এবং আরও অনেক কিছু।

Gemfile-এ জেমটি যোগ করুন:

Gemfile

ইনস্টল করুন:

তারপর rack_attack.rb ইনিশিয়ালাইজার ফাইলে কনফিগারেশন দিন। জেমের ডকুমেন্টেশনে সকল উপলব্ধ অপশন এবং কিছু ইউজ কেস সাজেস্ট করা রয়েছে। নিচের স্যাম্পল কনফিগ লোকালহোস্ট বাদে সবাকে সার্ভিস অ্যাক্সেস করতে বাধা দেবে এবং প্রতি সেকেন্ডে সর্বোচ্চ ৫টি রিকোয়েস্ট সীমাবদ্ধ করবে:

config/initializers/rack_attack.rb

এছাড়া একটা জিনিস করতে হবে: RackAttack কে মিডলওয়্যার হিসেবে ইনক্লুড করুন:

config/application.rb

উপসংহার

এই নিবন্ধের শেষে আসলাম। আশা করি এখন আপনি রেইলসে API তৈরি করার বিষয়ে আরও আত্মবিশ্বাসী অনুভব করছেন! লক্ষ্য করুন যে এটি একমাত্র উপলব্ধ অপশন নয়—অন্য একটি জনপ্রিয় সমাধান যা অনেকদিন থেকে আছে সেটি Grape ফ্রেমওয়ার্ক, তাই আপনি সেটিও চেক আউট করতে পারেন।

যদি কিছু অস্পষ্ট লাগে, প্রশ্ন পোস্ট করতে সংকোচ করবেন না। আমার সাথে থাকার জন্য ধন্যবাদ, এবং শুভ কোডিং!

  1. রুবি অন রেইলসে টেইলউইন্ড CSS যোগ করা: একটি প্র্যাকটিক্যাল ধাপে ধাপে গাইড

  2. রেইলস সিকিউরিটি: অথেন্টিকেশন ভালনারেবিলিটি vastaan প্রতিরক্ষা

  3. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি

  4. সিকিউর পাসওয়ার্ড সেটআপসহ অটোমেটেড লিনাক্স ইউজার ক্রিয়েশন