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