mirror of
https://github.com/hakanensari/frankfurter.git
synced 2024-11-24 20:15:15 +01:00
Switch to Roda
A first stab at replacing Sinatra with Roda
This commit is contained in:
parent
535471509b
commit
82666af2d6
@ -1,7 +1,7 @@
|
||||
Metrics/AbcSize:
|
||||
Max: 21.79
|
||||
Metrics/BlockLength:
|
||||
ExcludedMethods: ['describe', 'helpers']
|
||||
ExcludedMethods: ['describe', 'route']
|
||||
Metrics/MethodLength:
|
||||
Max: 13
|
||||
Minitest:
|
||||
|
3
Gemfile
3
Gemfile
@ -7,11 +7,12 @@ ruby '2.7.1'
|
||||
gem 'money'
|
||||
gem 'oj'
|
||||
gem 'ox'
|
||||
gem 'rack-contrib'
|
||||
gem 'rack-cors'
|
||||
gem 'rake'
|
||||
gem 'roda'
|
||||
gem 'rufus-scheduler'
|
||||
gem 'sequel_pg'
|
||||
gem 'sinatra'
|
||||
gem 'unicorn'
|
||||
|
||||
group :test do
|
||||
|
18
Gemfile.lock
18
Gemfile.lock
@ -25,8 +25,6 @@ GEM
|
||||
minitest (>= 4, < 6)
|
||||
money (6.13.7)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
mustermann (1.1.1)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
oj (3.10.6)
|
||||
ox (2.13.2)
|
||||
parallel (1.19.1)
|
||||
@ -36,16 +34,18 @@ GEM
|
||||
public_suffix (4.0.4)
|
||||
raabro (1.1.6)
|
||||
rack (2.2.2)
|
||||
rack-contrib (2.2.0)
|
||||
rack (~> 2.0)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-protection (2.0.8.1)
|
||||
rack
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.1)
|
||||
rake (13.0.1)
|
||||
rexml (3.2.4)
|
||||
roda (3.31.0)
|
||||
rack
|
||||
rubocop (0.82.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
@ -61,7 +61,6 @@ GEM
|
||||
rubocop-sequel (0.0.6)
|
||||
rubocop (~> 0.55, >= 0.55)
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby2_keywords (0.0.2)
|
||||
rufus-scheduler (3.6.0)
|
||||
fugit (~> 1.1, >= 1.1.6)
|
||||
safe_yaml (1.0.5)
|
||||
@ -73,12 +72,6 @@ GEM
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov-html (0.12.2)
|
||||
sinatra (2.0.8.1)
|
||||
mustermann (~> 1.0)
|
||||
rack (~> 2.0)
|
||||
rack-protection (= 2.0.8.1)
|
||||
tilt (~> 2.0)
|
||||
tilt (2.0.10)
|
||||
tzinfo (2.0.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (1.7.0)
|
||||
@ -101,16 +94,17 @@ DEPENDENCIES
|
||||
money
|
||||
oj
|
||||
ox
|
||||
rack-contrib
|
||||
rack-cors
|
||||
rack-test
|
||||
rake
|
||||
roda
|
||||
rubocop-minitest
|
||||
rubocop-performance
|
||||
rubocop-sequel
|
||||
rufus-scheduler
|
||||
sequel_pg
|
||||
simplecov
|
||||
sinatra
|
||||
unicorn
|
||||
vcr
|
||||
webmock
|
||||
|
@ -3,4 +3,4 @@
|
||||
require './config/environment'
|
||||
require 'web/server'
|
||||
|
||||
run Sinatra::Application
|
||||
run Web::Server.freeze.app
|
||||
|
@ -1,103 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'oj'
|
||||
require 'rack/contrib/jsonp'
|
||||
require 'rack/cors'
|
||||
require 'sinatra'
|
||||
require 'roda'
|
||||
|
||||
require 'currency_names'
|
||||
require 'query'
|
||||
require 'quote'
|
||||
|
||||
module Web
|
||||
class Server < Roda
|
||||
use Rack::Cors do
|
||||
allow do
|
||||
origins '*'
|
||||
resource '*', headers: :any, methods: :get
|
||||
resource '*', headers: :any, methods: %i[get options]
|
||||
end
|
||||
end
|
||||
use Rack::JSONP
|
||||
|
||||
plugin :caching
|
||||
|
||||
plugin :error_handler do |_error|
|
||||
request.halt [422, {}, nil]
|
||||
end
|
||||
|
||||
plugin :indifferent_params
|
||||
|
||||
plugin :json, content_type: 'application/json; charset=utf-8',
|
||||
serializer: ->(o) { Oj.dump(o, mode: :compat) }
|
||||
|
||||
plugin :params_capturing
|
||||
|
||||
route do |r|
|
||||
r.root do
|
||||
{ docs: 'https://www.frankfurter.app/docs' }
|
||||
end
|
||||
|
||||
r.is(/latest|current/) do
|
||||
r.params['date'] = Date.today.to_s
|
||||
quote = quote_end_of_day(r)
|
||||
r.etag quote.cache_key
|
||||
|
||||
quote.formatted
|
||||
end
|
||||
|
||||
r.is(/(\d{4}-\d{2}-\d{2})/) do
|
||||
r.params['date'] = r.params['captures'].first
|
||||
quote = quote_end_of_day(r)
|
||||
r.etag quote.cache_key
|
||||
|
||||
quote.formatted
|
||||
end
|
||||
|
||||
r.is(/(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})?/) do
|
||||
r.params['start_date'] = r.params['captures'].first
|
||||
r.params['end_date'] = r.params['captures'][1] || Date.today.to_s
|
||||
quote = quote_interval(r)
|
||||
r.etag quote.cache_key
|
||||
|
||||
quote.formatted
|
||||
end
|
||||
|
||||
r.is 'currencies' do
|
||||
currency_names = CurrencyNames.new
|
||||
r.etag currency_names.cache_key
|
||||
|
||||
currency_names.formatted
|
||||
end
|
||||
end
|
||||
|
||||
configure :development do
|
||||
set :show_exceptions, :after_handler
|
||||
end
|
||||
private
|
||||
|
||||
configure :production do
|
||||
disable :dump_errors
|
||||
end
|
||||
|
||||
configure :test do
|
||||
set :raise_errors, false
|
||||
end
|
||||
|
||||
set :static_cache_control, [:public, max_age: 300]
|
||||
|
||||
helpers do
|
||||
def end_of_day_quote
|
||||
@end_of_day_quote ||= begin
|
||||
query = Query.build(params)
|
||||
def quote_end_of_day(request)
|
||||
query = Query.build(request.params)
|
||||
quote = Quote::EndOfDay.new(**query)
|
||||
quote.perform
|
||||
halt 404 if quote.not_found?
|
||||
request.halt [404, {}, nil] if quote.not_found?
|
||||
|
||||
quote
|
||||
end
|
||||
end
|
||||
|
||||
def interval_quote
|
||||
@interval_quote ||= begin
|
||||
query = Query.build(params)
|
||||
def quote_interval(request)
|
||||
query = Query.build(request.params)
|
||||
quote = Quote::Interval.new(**query)
|
||||
quote.perform
|
||||
halt 404 if quote.not_found?
|
||||
request.halt [404, {}, nil] if quote.not_found?
|
||||
|
||||
quote
|
||||
end
|
||||
end
|
||||
|
||||
def json(data)
|
||||
json = Oj.dump(data, mode: :compat)
|
||||
callback = params['callback']
|
||||
|
||||
if callback
|
||||
content_type :js, charset: Encoding::UTF_8
|
||||
"#{callback}(#{json})"
|
||||
else
|
||||
content_type :json, charset: Encoding::UTF_8
|
||||
json
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
get '/' do
|
||||
json({ docs: 'https://www.frankfurter.app/docs' })
|
||||
end
|
||||
|
||||
get '/(?:latest|current)', mustermann_opts: { type: :regexp } do
|
||||
params[:date] = Date.today.to_s
|
||||
etag end_of_day_quote.cache_key
|
||||
json end_of_day_quote.formatted
|
||||
end
|
||||
|
||||
get '/(?<date>\d{4}-\d{2}-\d{2})', mustermann_opts: { type: :regexp } do
|
||||
etag end_of_day_quote.cache_key
|
||||
json end_of_day_quote.formatted
|
||||
end
|
||||
|
||||
get '/(?<start_date>\d{4}-\d{2}-\d{2})\.\.(?<end_date>\d{4}-\d{2}-\d{2})?',
|
||||
mustermann_opts: { type: :regexp } do
|
||||
@params[:end_date] ||= Date.today.to_s
|
||||
etag interval_quote.cache_key
|
||||
json interval_quote.formatted
|
||||
end
|
||||
|
||||
get '/currencies' do
|
||||
currency_names = CurrencyNames.new
|
||||
etag currency_names.cache_key
|
||||
json currency_names.formatted
|
||||
end
|
||||
|
||||
not_found do
|
||||
halt 404
|
||||
end
|
||||
|
||||
error do
|
||||
halt 422
|
||||
end
|
||||
|
@ -7,7 +7,7 @@ require 'web/server'
|
||||
describe 'the server' do
|
||||
include Rack::Test::Methods
|
||||
|
||||
let(:app) { Sinatra::Application }
|
||||
let(:app) { Web::Server.freeze }
|
||||
|
||||
def json
|
||||
Oj.load(last_response.body)
|
||||
|
@ -7,7 +7,7 @@ require 'web/server'
|
||||
describe 'the server' do
|
||||
include Rack::Test::Methods
|
||||
|
||||
let(:app) { Sinatra::Application }
|
||||
let(:app) { Web::Server.freeze }
|
||||
let(:json) { Oj.load(last_response.body) }
|
||||
let(:headers) { last_response.headers }
|
||||
|
||||
@ -100,11 +100,11 @@ describe 'the server' do
|
||||
|
||||
it 'handles JSONP' do
|
||||
get '/latest?callback=foo'
|
||||
_(last_response.body).must_be :start_with?, 'foo'
|
||||
_(last_response.body).must_be :start_with?, '/**/foo'
|
||||
end
|
||||
|
||||
it 'sets charset to UTF-8' do
|
||||
it 'sets charset to utf-8' do
|
||||
get '/currencies'
|
||||
_(last_response.headers['content-type']).must_be :end_with?, 'charset=UTF-8'
|
||||
_(last_response.headers['content-type']).must_be :end_with?, 'charset=utf-8'
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user