Rack::RequestReplication - Replicate Rack app HTTP requests
Replicate requests from one app instance to another. At Springest we used Gor once to test our new Postgres stack vs our at that time current MySQL stack. We replicated all live requests to our staging environment to test new code before it went live. With real traffic!
Unfortunately, we could not test everything we wanted with the setup with Gor. Stuff that relied on sessions (like MySpringest, and course management through our Admin panel) could not be tested properly because the staging environment did not share sessions with the production stack.
Recently, @foxycoder was asked to give a talk about these adventures at Amsterdam.rb. And while we were thinking about all the stuff that we needed to do to get it right with Gor, we came up with the concept of this gem.
Full control over the requests through Rack
This is Rack MiddleWare. And thanks to that, we have all the information and handy tools available to parse and alter request data before we forward it to another stack.
Features
At the moment, it just forwards the request with only a couple of changes:
- The host and/or port to match the stack to forward to.
- The session cookie – it stores a persistent link between the source app's session and the destination app's session in Redis.
- The CSRF token – same as the session, the destination app's
authenticity_token
is persistent and used in consecutive requests.
Session support
It has support for sessions. To make use of it, you need to have Redis running. Redis serves as a key-value store where sessions from the Source App are linked to sessions from the Forward App. This way both apps can have their own session management.
Rails's CSRF tokens
Rails uses a cross site scripting defense mechanism in the form of an
authenticity_token
parameter. Absense of it, or modifying it between
requests results in XSS errors. Therefore we needed to make sure these
were properly captured and replaced by the Forwarder before sending the
request to the other application.
CSRF tokens are also persisted in Redis and used in consecutive requests, by
updating params["authenticity_token"]
before handing off the request
to the replica app.
API Docs
Check out the official API docs
Installation
Add this line to your application's Gemfile:
gem 'rack-request_replication'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rack-request_replication
Usage
Sinatra Example
require 'sinatra/base'
require 'sinatra/cookies'
require 'rack/request_replication'
class TestApp < Sinatra::Base
# Forward all requests to another app that runs on localhost, port 4568
use Rack::RequestReplication::Forwarder,
host: 'localhost',
port: 4568,
session_key: 'rack.session',
redis: {
host: 'localhost',
port: 6379,
db: 'rack-request-replication'
}
get '/' do
'Hello World'
end
end
Supported Ruby Versions
We currently support the following Ruby versions:
- 1.9.3
- 2.1.6
- 2.2.2
- jruby (latest)
Please note that Rubinious is currently not supported.
Contributing
- Fork it ( https://github.com/[my-github-username]/rack-request_replication/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request