diff --git a/.rubocop.yml b/.rubocop.yml index 82c6d296b..efcd70e96 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -11,9 +11,6 @@ inherit_gem: Bridgetown/NoPutsAllowed: Exclude: - rake/*.rake - - bridgetown-core/lib/bridgetown-core/commands/base.rb - - bridgetown-core/lib/bridgetown-core/commands/plugins.rb - - bridgetown-core/lib/bridgetown-core/rack/roda.rb AllCops: TargetRubyVersion: 2.7 diff --git a/bridgetown-core/.rubocop.yml b/bridgetown-core/.rubocop.yml index 1b02eeeac..333cc662b 100644 --- a/bridgetown-core/.rubocop.yml +++ b/bridgetown-core/.rubocop.yml @@ -12,11 +12,15 @@ AllCops: - tmp/**/* - test/source/**/* - test/resources/src/_pages/*.rb + - lib/bridgetown-core/commands/base.rb + - lib/bridgetown-core/commands/plugins.rb + - lib/bridgetown-core/rack/roda.rb - lib/site_template/TEMPLATES/**/* - lib/site_template/Rakefile - lib/site_template/config.ru - lib/site_template/config/**/* - lib/site_template/plugins/site_builder.rb + - lib/site_template/server/roda_app.rb Lint/ConstantDefinitionInBlock: Exclude: diff --git a/bridgetown-core/lib/bridgetown-core/rack/roda.rb b/bridgetown-core/lib/bridgetown-core/rack/roda.rb index 5e46d4875..beeccf77b 100644 --- a/bridgetown-core/lib/bridgetown-core/rack/roda.rb +++ b/bridgetown-core/lib/bridgetown-core/rack/roda.rb @@ -2,6 +2,13 @@ require "rack/indifferent" +begin + # If it's in the Gemfile's :bridgetown_plugins group it's already been required, but we'll try + # again just to be on the safe side: + require "bridgetown-routes" +rescue LoadError +end + class Roda module RodaPlugins module BridgetownSSR @@ -12,6 +19,34 @@ def self.configure(app, _opts = {}, &block) end register_plugin :bridgetown_ssr, BridgetownSSR + + module BridgetownBoot + module InstanceMethods + # Helper shorthand for Bridgetown::Current.site + # @return [Bridgetown::Site] + def bridgetown_site + Bridgetown::Current.site + end + end + + Roda::RodaRequest.alias_method :_previous_roda_cookies, :cookies + + module RequestMethods + # Monkeypatch Roda/Rack's Request object so it returns a hash which allows for + # indifferent access + def cookies + # TODO: maybe replace with a simpler hash that offers an overloaded `[]` method + _previous_roda_cookies.with_indifferent_access + end + + # Starts up the Bridgetown routing system + def bridgetown + Bridgetown::Rack::Routes.start!(scope) + end + end + end + + register_plugin :bridgetown_boot, BridgetownBoot end end @@ -24,6 +59,7 @@ class Roda < ::Roda plugin :json_parser plugin :cookies plugin :streaming + plugin :bridgetown_boot plugin :public, root: Bridgetown::Current.preloaded_configuration.destination plugin :not_found do output_folder = Bridgetown::Current.preloaded_configuration.destination @@ -56,12 +92,6 @@ class Roda < ::Roda "

ERROR: cannot find index.html in the output folder.

" end end - - # Helper shorthand for Bridgetown::Current.site - # @return [Bridgetown::Site] - def bridgetown_site - Bridgetown::Current.site - end end end end diff --git a/bridgetown-core/lib/site_template/server/roda_app.rb b/bridgetown-core/lib/site_template/server/roda_app.rb index bfd452e85..eaebb69ae 100644 --- a/bridgetown-core/lib/site_template/server/roda_app.rb +++ b/bridgetown-core/lib/site_template/server/roda_app.rb @@ -4,21 +4,18 @@ # # Learn more at: http://roda.jeremyevans.net -# Uncomment to use file-based dynamic routing in your project (make sure you -# uncomment the gem dependency in your Gemfile as well): -# require "bridgetown-routes" - class RodaApp < Bridgetown::Rack::Roda # Add additional Roda configuration here if needed # Uncomment to use Bridgetown SSR: # plugin :bridgetown_ssr - # And optionally file-based routing: + # Uncomment to use file-based dynamic routing in your project (make sure you + # uncomment the gem dependency in your `Gemfile` as well): # plugin :bridgetown_routes route do |r| # Load Roda routes in server/routes (and src/_routes via `bridgetown-routes`) - Bridgetown::Rack::Routes.start! self + r.bridgetown end end diff --git a/bridgetown-core/test/ssr/server/roda_app.rb b/bridgetown-core/test/ssr/server/roda_app.rb index 7c7570f66..ecdff6a3c 100644 --- a/bridgetown-core/test/ssr/server/roda_app.rb +++ b/bridgetown-core/test/ssr/server/roda_app.rb @@ -6,7 +6,5 @@ class RodaApp < Bridgetown::Rack::Roda site.data.iterations += 1 end - route do |_r| - Bridgetown::Rack::Routes.start! self - end + route(&:bridgetown) end diff --git a/bridgetown-core/test/ssr/server/routes/cookies.rb b/bridgetown-core/test/ssr/server/routes/cookies.rb new file mode 100644 index 000000000..9da5d964c --- /dev/null +++ b/bridgetown-core/test/ssr/server/routes/cookies.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Routes::Cookies < Bridgetown::Rack::Routes + route do |r| + # route: GET /cookies + r.get "cookies" do + { value: r.cookies[:test_key] } + end + + # route: POST /cookies + r.post "cookies" do + response.set_cookie :test_key, { + value: r.params[:value], + httponly: true, + } + + { value: r.cookies[:test_key] } + end + end +end diff --git a/bridgetown-core/test/ssr/server/routes/ooh_json.rb b/bridgetown-core/test/ssr/server/routes/ooh_json.rb new file mode 100644 index 000000000..85ecf5446 --- /dev/null +++ b/bridgetown-core/test/ssr/server/routes/ooh_json.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class Routes::OohJson < Bridgetown::Rack::Routes + route do |r| + # route: POST /cookies + r.post "ooh_json" do + next { keep_on: "running" } unless r.params[:tell_me] == "what you're chasin'" + + { because_the_night: "will never give you what you want" } + end + end +end diff --git a/bridgetown-core/test/test_ssr.rb b/bridgetown-core/test/test_ssr.rb index 502eff9f5..e00091158 100644 --- a/bridgetown-core/test/test_ssr.rb +++ b/bridgetown-core/test/test_ssr.rb @@ -9,6 +9,10 @@ def app @@ssr_app ||= Rack::Builder.parse_file(File.expand_path("ssr/config.ru", __dir__)).first # rubocop:disable Style/ClassVars end + def site + app.opts[:bridgetown_site] + end + context "Roda-powered Bridgetown server" do setup do Bridgetown::Current.site = nil @@ -32,11 +36,22 @@ def app end should "preserve site data between live reloads" do - app # ensure it's been run - site = @@ssr_app.opts[:bridgetown_site] assert_equal 1, site.data.iterations site.reset(soft: true) assert_equal 2, site.data.iterations end + + should "support indifferent cookies" do + post "/cookies", value: "Gookie!" + get "/cookies" + assert last_response.ok? + assert_equal({ value: "Gookie!" }.to_json, last_response.body) + end + + should "support incoming JSON payloads" do + post "/ooh_json", { tell_me: "what you're chasin'" } + assert last_response.ok? + assert_equal({ because_the_night: "will never give you what you want" }.to_json, last_response.body) + end end end diff --git a/bridgetown-routes/lib/bridgetown-routes.rb b/bridgetown-routes/lib/bridgetown-routes.rb index 87ff0e6c6..fb23397d1 100644 --- a/bridgetown-routes/lib/bridgetown-routes.rb +++ b/bridgetown-routes/lib/bridgetown-routes.rb @@ -16,6 +16,7 @@ module Routes # rubocop:disable Bridgetown/NoPutsAllowed def self.print_roda_routes + # TODO: this needs to be fully documented, currently no info on how to generate .routes.json routes = begin JSON.parse(File.read("#{Dir.pwd}/.routes.json")) rescue StandardError diff --git a/bridgetown-website/server/roda_app.rb b/bridgetown-website/server/roda_app.rb index 619d1f7e7..8efa8a48f 100644 --- a/bridgetown-website/server/roda_app.rb +++ b/bridgetown-website/server/roda_app.rb @@ -7,9 +7,7 @@ class RodaApp < Bridgetown::Rack::Roda plugin :bridgetown_ssr - route do - # Load all the files in server/routes - # see hello.rb.sample - Bridgetown::Rack::Routes.start! self + route do |r| + r.bridgetown end end diff --git a/bridgetown-website/src/_docs/routes.md b/bridgetown-website/src/_docs/routes.md index da0d8699f..dbe732c4e 100644 --- a/bridgetown-website/src/_docs/routes.md +++ b/bridgetown-website/src/_docs/routes.md @@ -157,12 +157,6 @@ To opt-into the `bridgetown-routes` gem, make sure it's enabled in your `Gemfile gem "bridgetown-routes", group: :bridgetown_plugins ``` -and required at the top of your `server/roda_app.rb` file: - -```ruby -require "bridgetown-routes" -``` - and added in as a Roda plugin below the SSR plugin: ```ruby