From b4b0e233b501895d2aa3d8ed79cdfaaae13563d2 Mon Sep 17 00:00:00 2001 From: Vitaliy Supron Date: Thu, 13 Jul 2023 05:55:08 +0300 Subject: [PATCH] feat: rack time format --- Gemfile | 4 ++++ Gemfile.lock | 19 +++++++++++++++++++ app.rb | 33 +++++++++++++++++++++++++++++++++ config.ru | 7 +++++++ log/app.log | 2 ++ middleware/logger.rb | 15 +++++++++++++++ time_format.rb | 28 ++++++++++++++++++++++++++++ 7 files changed, 108 insertions(+) create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 app.rb create mode 100644 config.ru create mode 100644 log/app.log create mode 100644 middleware/logger.rb create mode 100644 time_format.rb diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..0fb1318 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'pry' +gem 'rack', '~> 1.6', '>= 1.6.4' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..65ea907 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,19 @@ +GEM + remote: https://rubygems.org/ + specs: + coderay (1.1.3) + method_source (1.0.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + rack (1.6.13) + +PLATFORMS + x86_64-darwin-22 + +DEPENDENCIES + pry + rack (~> 1.6, >= 1.6.4) + +BUNDLED WITH + 2.3.22 diff --git a/app.rb b/app.rb new file mode 100644 index 0000000..08ba16d --- /dev/null +++ b/app.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require_relative 'time_format' + +class App + def call(env) + request = Rack::Request.new(env) + return not_found unless request.get? && request.path == '/time' + + time_format = TimeFormat.new(request.params['format']&.split(',')) + + if time_format.unknown_formats.empty? + response(body: time_format.formatted_time) + else + bad_request("Unknown time format [#{time_format.unknown_formats.join(',')}]") + end + end + + private + + def not_found + response(status: 404) + end + + def bad_request(body) + response(status: 400, body: body) + end + + def response(status: 200, headers: {}, body: []) + response = Rack::Response.new(body, status, headers) + response.finish + end +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..7b4d4d1 --- /dev/null +++ b/config.ru @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require_relative 'app' +require_relative 'middleware/logger' + +use AppLogger, logdev: File.expand_path('log/app.log', __dir__) +run App.new diff --git a/log/app.log b/log/app.log new file mode 100644 index 0000000..5570e4c --- /dev/null +++ b/log/app.log @@ -0,0 +1,2 @@ +# Logfile created on 2023-07-13 05:54:24 +0300 by logger.rb/v1.4.2 +I, [2023-07-13T05:54:33.501996 #62736] INFO -- : {"GATEWAY_INTERFACE"=>"CGI/1.1", "PATH_INFO"=>"/time", "QUERY_STRING"=>"format=year%2Cmonth%2Cdays%2Cdd", "REMOTE_ADDR"=>"127.0.0.1", "REMOTE_HOST"=>"127.0.0.1", "REQUEST_METHOD"=>"GET", "REQUEST_URI"=>"http://localhost:9292/time?format=year%2Cmonth%2Cdays%2Cdd", "SCRIPT_NAME"=>"", "SERVER_NAME"=>"localhost", "SERVER_PORT"=>"9292", "SERVER_PROTOCOL"=>"HTTP/1.1", "SERVER_SOFTWARE"=>"WEBrick/1.6.1 (Ruby/2.7.6/2022-04-12)", "HTTP_HOST"=>"localhost:9292", "HTTP_USER_AGENT"=>"curl/7.85.0", "HTTP_ACCEPT"=>"*/*", "rack.version"=>[1, 3], "rack.input"=>#>, "rack.errors"=>#>>, "rack.multithread"=>true, "rack.multiprocess"=>false, "rack.run_once"=>false, "rack.url_scheme"=>"http", "rack.hijack?"=>true, "rack.hijack"=>#, "rack.hijack_io"=>nil, "HTTP_VERSION"=>"HTTP/1.1", "REQUEST_PATH"=>"/time", "rack.tempfiles"=>[]} diff --git a/middleware/logger.rb b/middleware/logger.rb new file mode 100644 index 0000000..cb08860 --- /dev/null +++ b/middleware/logger.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'logger' + +class AppLogger + def initialize(app, **options) + @logger = Logger.new(options[:logdev] || $stdout) + @app = app + end + + def call(env) + @logger.info(env) + @app.call(env) + end +end diff --git a/time_format.rb b/time_format.rb new file mode 100644 index 0000000..d16089f --- /dev/null +++ b/time_format.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class TimeFormat + FORMATS = { + 'year' => '%Y', + 'month' => '%m', + 'day' => '%d', + 'hour' => '%H', + 'minute' => '%M', + 'second' => '%S' + }.freeze + + def initialize(formats) + @formats = formats || [] + end + + def valid_formats + @formats.select { |format| FORMATS.include?(format) } + end + + def unknown_formats + @formats - FORMATS.keys + end + + def formatted_time + valid_formats.map { |format| Time.now.strftime(FORMATS[format]) }.join('-') + end +end