Will repeat at least until we run out of banitsa.
May change them dates and times.
May change locations.
May have presentations.
rack + net/http = ❤️
In a micro-service, API-oriented world, you need an API gateway.
Or so I'm told, I dunno, really.
Infrastructure
Infrastructure
Application
Or nginx sucks, right?
BUT IT DOESN'T SCALE, BRAH!
IT'S SLOWOLOLOLO!
SO WHAT?
SO FUCKING WHAT?
HAS BEEN IN PRODUCTION FOR YEARS!
IT'S FINE!
require 'rack'
app = proc do |env|
['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']]
end
Rack::Handler::WEBrick.run app
Rack provides a minimal interface between web servers supporting Ruby and Ruby frameworks.
A Rack application is a Ruby object (not a class) that responds to #call.
It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.
The environment must be an instance of Hash that includes CGI-like headers.
The application is free to modify the environment.
The environment is required to have a couple required keys (adopted from PEP333).
The foundation of an HTTP middleware in the Ruby 🌍
class Middleware
def initialize(app)
@app = app
end
def call(env)
# Pass control to the previous application if you need to.
@app.call(env)
end
end
class Middleware
def initialize(app)
@app = app
end
def call(env)
# Or stop the request here and return.
['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']]
end
end
The foundation of an HTTP middleware in the Ruby 🌍
Rack::MethodOverride Rack::Cors Rack::Sendfile ActionDispatch::Static ActionDispatch::Executor ActiveSupport::Cache::Strategy::LocalCache::Middleware Rack::Runtime ActionDispatch::RequestId ActionDispatch::RemoteIp Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions ActionDispatch::Reloader ActionDispatch::Callbacks ActiveRecord::Migration::CheckPending Rack::Head Rack::ConditionalGet Rack::ETag Rack::Deflater Some::Application.routes
ProxyMiddleware = Struct.new(:app) do
def call(env)
if should_proxy_request?(env)
proxy_request_to_another_service(env)
else
app.call(env)
end
end
# ...
end
kinda/sorta
Decide which requests to proxy
Rewrite request paths
Handle timeouts
Configuration
Macro::ApiGateway = Rack::Delegate.configure do
# Strips the leading /api out of the outgoing requests.
rewrite { path.gsub!(%r{\A/api}, '') }
# Don't proxy requests without them matching on the condition in the block.
constraints { |request| Version.new('v1').matches?(request) }
# With the rewrite on, requests you /api/users will go to
# http://users-service.intern/users.
from %r{\A/api/users}, to: 'http://users-service.intern'
# Requests go to http://payments-service.intern/payments.
from %r{\A/api/payments}, to: 'http://payments-service.intern'
end
module Macro
class Appplication
middleware.use ApiGateway
end
end
Pre-process requests
Proxy the request