Saturday, May 10, 2025
News PouroverAI
Visit PourOver.AI
No Result
View All Result
  • Home
  • AI Tech
  • Business
  • Blockchain
  • Data Science & ML
  • Cloud & Programming
  • Automation
  • Front-Tech
  • Marketing
  • Home
  • AI Tech
  • Business
  • Blockchain
  • Data Science & ML
  • Cloud & Programming
  • Automation
  • Front-Tech
  • Marketing
News PouroverAI
No Result
View All Result

How to build a Rails API with rate limiting

June 4, 2024
in Front-Tech
Reading Time: 17 mins read
0 0
A A
0
Share on FacebookShare on Twitter


APIs are essential for the internet. They allow applications to interact programmatically, making developers’ lives easier. However, web applications are often targeted by malicious actors, which is why rate limiting is crucial for API security. In this guide, we’ll use Ruby on Rails to create an API application for managing an animal shelter and integrate rate limiting with rack-attack. We’ll track cats, dogs, and volunteers through a JSON interface.

You can follow along with the example app we create and view the final app’s source code on Github. Let’s dive in!

Installing Ruby

If you don’t have Ruby installed, you’ll need to do so. I’ll be using Ruby 3.2 in this tutorial. It’s recommended to use a Ruby version manager like rbenv if you’re starting fresh. You can install rbenv with Homebrew:

Next, install Ruby 3.2.0 using rbenv:

Then, set rbenv to use this Ruby version for your current directory:

Installing Rails

Now that you have Ruby installed, it’s time to install Rails. We’ll be using Rails 7.1.1 in this tutorial. You can install it by running:

gem install rails -v 7.1.1

Generating a new Rails project

Rails is a full-stack framework, but you can generate an API-only project if you only need to serve JSON data. This is useful for integration with mobile apps, SPAs, or other services. Create a new Rails 7.1.1 API project with:

rails _7.1.1_ new animal-shelter –api

Then, navigate to the directory of the new application, in this case, animal-shelter.

For this example, we’ll focus on improving the operations of an animal shelter. We’ll create API endpoints for cats, dogs, and volunteers. While this may not be practical on its own, it sets the foundation for more advanced features. If you want to name your application differently, replace “animal-shelter” in the command above.

Using Rails scaffolds for tracking cats

To create, read, update, and delete cats, we’ll use Rails scaffolding. This will generate models, controllers, and a migration file. Run the following command in your application:

rails generate scaffold Cat name:string arrival_date:datetime description:text –api

This command generates various files necessary for managing cats.

Run the pending database migration created by the scaffold:

Inspecting the cats code

In the app/controllers/cats_controller.rb file, you’ll find prepopulated methods that enable HTTP requests for creating, reading, updating, and deleting cats. Here’s the cats controller:

class CatsController < ApplicationController
before_action :set_cat, only: %i[ show update destroy ]

# GET /cats
def index
@cats = Cat.all

render json: @cats
end

# GET /cats/1
def show
render json: @cat
end

# POST /cats
def create
@cat = Cat.new(cat_params)

if @cat.save
render json: @cat, status: :created, location: @cat
else
render json: @cat.errors, status: :unprocessable_entity
end
end

# PATCH/PUT /cats/1
def update
if @cat.update(cat_params)
render json: @cat
else
render json: @cat.errors, status: :unprocessable_entity
end
end

# DELETE /cats/1
def destroy
@cat.destroy!
end

private
# Use callbacks to share common setup or constraints between actions.
def set_cat
@cat = Cat.find(params[:id])
end

# Only allow a list of trusted parameters through.
def cat_params
params.require(:cat).permit(:name, :arrival_date, :description)
end
end

Testing the cats code

You can test the functionality by using curl or a tool like Postman. Send a POST request to localhost:3000/cats with the specified body to create a cat in the database:

{
“name”: “Bear”,
“description”: “Bear is aloof but loving. She prefers not to be picked up, but in her own time will join happily you for a cuddle.”,
“arrival_date”: “2024-01-28 14:11:09.818508”
}

This will create a new cat in the database and return a 201 HTTP status with the created object in the response:

{
“id”: 1,
“name”: “Bear”,
“arrival_date”: “2024-01-28T14:11:09.818Z”,
“description”: “Bear is aloof but loving. She prefers not to be picked up, but in her own time will join happily you for a cuddle.”
}

She prefers not to be picked up, but in her own time will join happily you for a cuddle.”,
“created_at”: “2024-01-28T19:13:51.047Z”,
“updated_at”: “2024-01-28T19:13:51.047Z”
}

Manually building endpoints for tracking dogs

Using Rails’ generators is incredibly convenient, and you have the opportunity to edit the generated files. Still, it’s not great for learning purposes. We’ll build a set of endpoints for CRUD operations on a ‘dog’ resource next, this time without the generators.

Creating a model

First, we’ll create the model file. In app/models, create a new file called dog.rb. The file doesn’t need a lot, just a class name and the class it should inherit from:

class Dog < ApplicationRecord
end

Inheriting from ApplicationRecord tells Rails that this is a model and provides the class with a set of methods that it will need. Next, we’ll create the necessary table in the database to persist records of dogs. We’ll first create a new migration by running:

Creating a new database table

rails generate migration CreateDogs

This creates a new timestamped file in the db/migrations directory. In that file, you’ll see a change method, which will be executed when the migration is run. The change method already creates a new table with the right name but is missing the rows we want. Change the migration to this:

class CreateDogs < ActiveRecord::Migration[7.1]
def change
create_table :dogs do |t|
t.string :name
t.datetime :arrival_date
t.text :description

t.timestamps
end
end
end

Next, run the migration with:

Creating routes for the dog resource

Next, we must create routes telling the application where to send incoming web requests. These are defined in config/routes.rb with a DSL that makes this convenient. Inside the code block (before the final end), add this line:

Writing the DogsController

Finally, we’ll write out the DogsController, which will handle CRUD actions for the dog resource. Create a new file in app/controllers/ called dogs_controller.rb There are a few different ways to write the code as long as you contain write the appropriate public methods, but you can speed things up by copying the CatsController and replacing every cat with dog:

class DogsController < ApplicationController
before_action :set_dog, only: %i[ show update destroy ]

# GET /dogs
def index
@dogs = Dog.all

render json: @dogs
end

# GET /dogs/1
def show
render json: @dog
end

# POST /dogs
def create
@dog = Dog.new(dog_params)

if @dog.save
render json: @dog, status: :created, location: @dog
else
render json: @dog.errors, status: :unprocessable_entity
end
end

# PATCH/PUT /dogs/1
def update
if @dog.update(dog_params)
render json: @dog
else
render json: @dog.errors, status: :unprocessable_entity
end
end

# DELETE /dogs/1
def destroy
@dog.destroy!
end

private
# Use callbacks to share common setup or constraints between actions.
def set_dog
@dog = Dog.find(params[:id])
end

# Only allow a list of trusted parameters through.
def dog_params
params.require(:dog).permit(:name, :arrival_date, :description)
end
end

Testing the DogsController

Finally, you can create, read, update, and delete dogs via the API just like you can for cats! Restart your rails server with rails s, then you can use Postman to create a new dog like this:


A screenshot of creating a dog with the API via Postman

Using scaffolds to build endpoints for tracking volunteers

Lastly, we’ll use the scaffold again to create endpoints for tracking volunteers. To start, run:

rails generate scaffold Volunteer name:string cumulative_hours:integer –api

Next, run the newly generated migration with:

This gives us everything we need for volunteers!

Integrating rack-attack for rate limiting

Now that we have a working Rails API with three different resources, we have a functional application for which we can add rate limiting! Rate limiting helps protect your application against malicious actors. Put simply, it throttles the amount of requests that someone can make to the API in a given time period. This adds a layer of protection to mitigate scraping, DoS, DDoS, and brute force attacks.

We can use a popular Ruby Gem called rack-attack to add rate limiting to this API. First, add the gem to the Gemfile:

Next, install it with:

Next, we’ll configure rack-attack. Create a new file in config/initializers called rack-attack.rb.
In that configuration, we’ll add the setup from rack’s documentation. We’ll strip out all of the configuration except that which throttles requests by IP.

Your config should look like this:

class Rack::Attack

### Configure Cache ###

# If you don’t want to use Rails.cache (Rack::Attack’s default), then
# configure it here.
#
# Note: The store is only used for throttling (not blocklisting and
# safelisting). It must implement .increment and .write like
# ActiveSupport::Cache::Store

# Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

### Throttle Spammy Clients ###

# If any single client IP is making tons of requests, then they’re
# probably malicious or a poorly-configured scraper. Either way, they
# don’t deserve to hog all of the app server’s CPU. Cut them off!
#
# Note: If you’re serving assets through rack, those requests may be
# counted by rack-attack, and this throttle may be activated too
# quickly. If so, enable the condition to exclude them from tracking.

# Throttle all requests by IP (60rpm)
#
# Key: “rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}”
throttle(‘req/ip’, limit: 300, period: 5.minutes) do |req|
req.ip # unless req.path.start_with?(‘/assets’)
end

### Custom Throttle Response ###

# By default, Rack::Attack returns an HTTP 429 for throttled responses,
# which is just fine.
#
# If you want to return 503 so the attacker might be fooled into
# believing that they’ve successfully broken your app (or you just want to
# customize the response), then uncomment these lines.
# self.throttled_responder = lambda do |env|
# [ 503, # status
# {}, # headers
# [”]] # body
# end
end

This contains helpful comments and sets a throttle for the entire application. If the application receives more than 300 requests in a 5-minute period, it will return a 429.

Testing our rate limiting

We can test our rate limiting in a number of ways, so let’s first create a few more cats in the database with a few POST /cats to our application. Once we’ve done that, we can GET /cats and see an array of existing cats in our database.

A screenshot of Postman getting an index of all cats
A screenshot of Postman getting an index of all cats

Next, we can temporarily change our configuration in rack-attack.rb to allow even fewer requests per 5-minute period.

# Throttle all requests by IP (60rpm)
#
# Key: “rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}”
throttle(‘req/ip’, limit: 5, period: 5.minutes) do |req|
req.ip # unless req.path.start_with?(‘/assets’)
end

Also, we’ll need to add in a chunk of code that configures rack-attack to use the MemoryStore cache if Redis is not present. Without this, rack-attack will not work in development, as the default cache in development is :null_store. In rack-attack.rb, add:

if !ENV[‘REDIS_URL’] || Rails.env.test?
cache.store = ActiveSupport::Cache::MemoryStore.new
end

Without the placeholder comments, rack-attack.rb now looks like:

class Rack::Attack
if !ENV[‘REDIS_URL’] || Rails.env.test?
cache.store = ActiveSupport::Cache::MemoryStore.new
end

# Throttle all requests by IP (60rpm)
# Key: “rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}”
throttle(‘req/ip’, limit: 5, period: 5.minutes) do |req|
req.ip # unless req.path.start_with?(‘/assets’)
end
end

Lastly, you can use Postman to make six subsequent requests to the application on any endpoint. Six requests to GET /cats now returns a 429!

A screenshot of Postman getting rate limited
A screenshot of Postman getting rate limited

This application-wide rate limiting is a great catch-all, but rack-attack allows you to do much more! You can limit specific endpoints, limit the total number of requests (disregarding source IP), blocklist, safelist, and more!

Conclusion

This tutorial has provided a comprehensive guide to building a Ruby on Rails API application with rate limiting to protect it! We’ve explored using the scaffold to quickly generate endpoints and also creating them manually. Rate limiting using rack-attack is a very helpful feature, safeguarding our application against abuse. With these tools and techniques at your disposal, you’re now equipped to create robust and efficient Rails API applications tailored to your specific needs. I encourage you to explore the rack-attack documentation to learn more about rate limiting at a more granular level than we explored.

It is important to always wear a helmet while riding a bicycle.

Make sure to properly adjust the straps and ensure a snug fit to protect your head in case of a fall.

Stay safe and happy riding!

HTML tags allow you to format and structure your content on the web. They provide a way to create headings, paragraphs, lists, links, images, and more. By using HTML tags, you can control the appearance and layout of your web pages, making them more visually appealing and easier to read.



Source link

Tags: APIBuildlimitingRailsrate
Previous Post

NFT Sales Hit Lowest Point Since October

Next Post

Wayanad Lok Sabha election results 2024 live: Rahul Gandhi leading with over 1.28 lakh votes

Related Posts

The essential principles of a good homepage
Front-Tech

The essential principles of a good homepage

June 7, 2024
How to measure and improve user retention
Front-Tech

How to measure and improve user retention

June 6, 2024
Push Animation on Grid Items
Front-Tech

Push Animation on Grid Items

June 5, 2024
Introduction to the B.I.A.S. framework
Front-Tech

Introduction to the B.I.A.S. framework

June 3, 2024
Blue Ridge Ruby is exactly what we need
Front-Tech

Blue Ridge Ruby is exactly what we need

June 3, 2024
Symmetrical and asymmetrical balance in web design
Front-Tech

Symmetrical and asymmetrical balance in web design

May 31, 2024
Next Post
Wayanad Lok Sabha election results 2024 live: Rahul Gandhi leading with over 1.28 lakh votes

Wayanad Lok Sabha election results 2024 live: Rahul Gandhi leading with over 1.28 lakh votes

Bank of America lays out the perfect scenario for stocks to rally after the May jobs report

Bank of America lays out the perfect scenario for stocks to rally after the May jobs report

23 Plagiarism Facts and Statistics to Analyze Latest Trends

23 Plagiarism Facts and Statistics to Analyze Latest Trends

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • Trending
  • Comments
  • Latest
Is C.AI Down? Here Is What To Do Now

Is C.AI Down? Here Is What To Do Now

January 10, 2024
Porfo: Revolutionizing the Crypto Wallet Landscape

Porfo: Revolutionizing the Crypto Wallet Landscape

October 9, 2023
A Complete Guide to BERT with Code | by Bradney Smith | May, 2024

A Complete Guide to BERT with Code | by Bradney Smith | May, 2024

May 19, 2024
How To Build A Quiz App With JavaScript for Beginners

How To Build A Quiz App With JavaScript for Beginners

February 22, 2024
Saginaw HMI Enclosures and Suspension Arm Systems from AutomationDirect – Library.Automationdirect.com

Saginaw HMI Enclosures and Suspension Arm Systems from AutomationDirect – Library.Automationdirect.com

December 6, 2023
Part 1: ABAP RESTful Application Programming Model (RAP) – Introduction

Part 1: ABAP RESTful Application Programming Model (RAP) – Introduction

November 20, 2023
Can You Guess What Percentage Of Their Wealth The Rich Keep In Cash?

Can You Guess What Percentage Of Their Wealth The Rich Keep In Cash?

June 10, 2024
AI Compared: Which Assistant Is the Best?

AI Compared: Which Assistant Is the Best?

June 10, 2024
How insurance companies can use synthetic data to fight bias

How insurance companies can use synthetic data to fight bias

June 10, 2024
5 SLA metrics you should be monitoring

5 SLA metrics you should be monitoring

June 10, 2024
From Low-Level to High-Level Tasks: Scaling Fine-Tuning with the ANDROIDCONTROL Dataset

From Low-Level to High-Level Tasks: Scaling Fine-Tuning with the ANDROIDCONTROL Dataset

June 10, 2024
UGRO Capital: Targeting to hit milestone of Rs 20,000 cr loan book in 8-10 quarters: Shachindra Nath

UGRO Capital: Targeting to hit milestone of Rs 20,000 cr loan book in 8-10 quarters: Shachindra Nath

June 10, 2024
Facebook Twitter LinkedIn Pinterest RSS
News PouroverAI

The latest news and updates about the AI Technology and Latest Tech Updates around the world... PouroverAI keeps you in the loop.

CATEGORIES

  • AI Technology
  • Automation
  • Blockchain
  • Business
  • Cloud & Programming
  • Data Science & ML
  • Digital Marketing
  • Front-Tech
  • Uncategorized

SITEMAP

  • Disclaimer
  • Privacy Policy
  • DMCA
  • Cookie Privacy Policy
  • Terms and Conditions
  • Contact us

Copyright © 2023 PouroverAI News.
PouroverAI News

No Result
View All Result
  • Home
  • AI Tech
  • Business
  • Blockchain
  • Data Science & ML
  • Cloud & Programming
  • Automation
  • Front-Tech
  • Marketing

Copyright © 2023 PouroverAI News.
PouroverAI News

Welcome Back!

Login to your account below

Forgotten Password? Sign Up

Create New Account!

Fill the forms bellow to register

All fields are required. Log In

Retrieve your password

Please enter your username or email address to reset your password.

Log In