From df46cd644d33b30c730e28b568fc942be9ac8043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D1=88=D0=BD=D1=8F=D0=BA=D0=B8=D0=BD=20=D0=90=D0=BB?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20=D0=92=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 29 Dec 2023 12:08:29 +0300 Subject: [PATCH 1/3] init commit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e9b8235c..653a4d24 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,5 @@ ## The application overview Simpler application is a singleton instance of the `Simpler::Application` class. For convenience it can be obtained by calling `Simpler.application` method. This instance holds all the routes and responds to `call` method which is required by the Rack interface. + +Init commit message From a51b34e19694b9bcf9c12668ada2bdc5d8aa7a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D1=88=D0=BD=D1=8F=D0=BA=D0=B8=D0=BD=20=D0=90=D0=BB?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20=D0=92=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 9 Jan 2024 01:05:26 +0300 Subject: [PATCH 2/3] add task files; --- README.md | 2 -- app/controllers/tests_controller.rb | 9 ++++++ config.ru | 2 ++ config/routes.rb | 2 ++ lib/simpler/application.rb | 3 ++ lib/simpler/controller.rb | 43 +++++++++++++++++++++++++++-- lib/simpler/router.rb | 12 +++++++- lib/simpler/router/route.rb | 19 +++++++++++++ logs/log.txt | 21 ++++++++++++++ middleware/logger.rb | 36 ++++++++++++++++++++++++ 10 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 logs/log.txt create mode 100644 middleware/logger.rb diff --git a/README.md b/README.md index 653a4d24..e9b8235c 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,3 @@ ## The application overview Simpler application is a singleton instance of the `Simpler::Application` class. For convenience it can be obtained by calling `Simpler.application` method. This instance holds all the routes and responds to `call` method which is required by the Rack interface. - -Init commit message diff --git a/app/controllers/tests_controller.rb b/app/controllers/tests_controller.rb index 1526a689..e221faf6 100644 --- a/app/controllers/tests_controller.rb +++ b/app/controllers/tests_controller.rb @@ -4,8 +4,17 @@ def index @time = Time.now end + def show + render plain: params['id'] + end + def create end + def render_plain + headers['Content-Type'] = 'text/plain' + render plain: "Plain text response" + end + end diff --git a/config.ru b/config.ru index 3060cc20..e065e105 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,5 @@ require_relative 'config/environment' +require_relative 'middleware/logger' +use Logger run Simpler.application diff --git a/config/routes.rb b/config/routes.rb index 4a751251..304b05d6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Simpler.application.routes do + get '/tests/:id', 'tests#show' + get '/plain', 'tests#render_plain' get '/tests', 'tests#index' post '/tests', 'tests#create' end diff --git a/lib/simpler/application.rb b/lib/simpler/application.rb index 711946a9..a2bd4b3c 100644 --- a/lib/simpler/application.rb +++ b/lib/simpler/application.rb @@ -28,6 +28,8 @@ def routes(&block) def call(env) route = @router.route_for(env) + return @router.not_found(env) unless route + route.extract_params(env) controller = route.controller.new(env) action = route.action @@ -51,6 +53,7 @@ def setup_database end def make_response(controller, action) + # binding.pry controller.make_response(action) end diff --git a/lib/simpler/controller.rb b/lib/simpler/controller.rb index 9383b035..6cedec00 100644 --- a/lib/simpler/controller.rb +++ b/lib/simpler/controller.rb @@ -8,7 +8,9 @@ class Controller def initialize(env) @name = extract_name @request = Rack::Request.new(env) + @request.params.merge!(env['params']) @response = Rack::Response.new + @already_rendered = false end def make_response(action) @@ -17,7 +19,7 @@ def make_response(action) set_default_headers send(action) - write_response + write_response unless @already_rendered @response.finish end @@ -36,18 +38,55 @@ def write_response body = render_body @response.write(body) + @already_rendered = true end def render_body View.new(@request.env).render(binding) end + def render_string(template) + @request.env['simpler.template'] = template + end + + def render_error(error_message) + status 500 + @response.write(error_message) + @response.finish + end + + def render_hash(params) + if params.key?(:plain) + @request.env['simpler.render'] = :plain + @response.write(params[:plain].to_s) + @response.finish + else + render_error("Cannot render template with #{params.keys} options") + end + end + + def status(status) + response.status = status + end + + def headers + @response.headers + end + def params @request.params end def render(template) - @request.env['simpler.template'] = template + case template + when String + render_string(template) + when Hash + render_hash(template) + else + render_error("Cannot render #{template.class} template") + end + @already_rendered = true end end diff --git a/lib/simpler/router.rb b/lib/simpler/router.rb index 14b3415c..cd6450ee 100644 --- a/lib/simpler/router.rb +++ b/lib/simpler/router.rb @@ -1,4 +1,4 @@ -require_relative 'router/route' + require_relative 'router/route' module Simpler class Router @@ -22,6 +22,16 @@ def route_for(env) @routes.find { |route| route.match?(method, path) } end + def not_found(env) + method = env['REQUEST_METHOD'].downcase.to_sym + path = env['PATH_INFO'] + Rack::Response.new.then do |response| + response.status = 404 + response.write("[#{method} #{path}] route for current application is not found\n") + response.finish + end + end + private def add_route(method, path, route_point) diff --git a/lib/simpler/router/route.rb b/lib/simpler/router/route.rb index 4c66b4b7..d1256726 100644 --- a/lib/simpler/router/route.rb +++ b/lib/simpler/router/route.rb @@ -13,6 +13,25 @@ def initialize(method, path, controller, action) def match?(method, path) @method == method && path.match(@path) + @method == method && path.match(to_regex(@path)) + end + + def extract_params(env) + request_path_items = env['PATH_INFO'].split('/') + path_items = @path.split('/').map { |item| item.sub(':', '') } + + params = Hash[path_items.zip(request_path_items)].delete_if { |k, v| k == v } + env['params'] = params + end + + private + + def to_regex(path) + path.split('/') + .map { |string| string.start_with?(':') ? '\d+' : string } + .join('/') + .concat('$') + .then { |regex| Regexp.new regex } end end diff --git a/logs/log.txt b/logs/log.txt new file mode 100644 index 00000000..9e48f88c --- /dev/null +++ b/logs/log.txt @@ -0,0 +1,21 @@ + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#render_plain + Parameters: {} + Response: 200 [text/plain] plain + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"125"} + Response: 200 [text/html] plain + \ No newline at end of file diff --git a/middleware/logger.rb b/middleware/logger.rb new file mode 100644 index 00000000..f5e78b7a --- /dev/null +++ b/middleware/logger.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +class Logger + def initialize(app) + @app = app + end + + def call(env) + @env = env + status, headers, body = @app.call(env) + + log_content = collect_logs(status, headers, body) + logging(log_content) + + [status, headers, body] + end + + def logging(content) + filepath = File.expand_path('logs/log.txt') + write_mode = File.exist?(filepath) ? 'a' : 'w' + File.write(filepath, content, mode: write_mode) + end + + def collect_logs(status, headers, _body) + controller = @env['simpler.controller'].class.name + action = @env['simpler.action'] + template = @env['simpler.template'] || @env['simpler.render'] + parameters = @env['params'] + """ + Request: #{@env['REQUEST_METHOD']} + Handler: #{controller}##{action} + Parameters: #{parameters} + Response: #{status} [#{headers['Content-Type']}] #{template} + """ + end +end From f800b0d00cb1aa6cb5afc6b9bf1133d9391bcb45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D1=88=D0=BD=D1=8F=D0=BA=D0=B8=D0=BD=20=D0=90=D0=BB?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20=D0=92=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Tue, 9 Jan 2024 01:08:08 +0300 Subject: [PATCH 3/3] add task files; --- lib/simpler/application.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/simpler/application.rb b/lib/simpler/application.rb index a2bd4b3c..61d40be2 100644 --- a/lib/simpler/application.rb +++ b/lib/simpler/application.rb @@ -53,7 +53,6 @@ def setup_database end def make_response(controller, action) - # binding.pry controller.make_response(action) end