diff --git a/lib/prism/middleware/params.rb b/lib/prism/middleware/params.rb new file mode 100644 index 0000000..a16b368 --- /dev/null +++ b/lib/prism/middleware/params.rb @@ -0,0 +1,44 @@ +module Prism + module Middleware + class ParamsParser + def initialize(app) + @app = app + end + + def call(env) + request = Request.new(env) + body = request.body + rewind(env) + + if json_body?(request, body) && !valid_json?(body) + return bad_request + end + + @app.call(env) + end + + private + + def rewind(env) + input = env['rack.input'] + input.rewind if input.respond_to?(:rewind) + end + + def json_body?(request, body) + request.content_type.to_s.include?('application/json') && !body.empty? + end + + def valid_json?(body) + JSON.parse(body) + true + rescue JSON::ParserError + false + end + + def bad_request + payload = JSON.generate(error: 'invalid JSON body') + [400, { 'Content-Type' => 'application/json' }, [payload]] + end + end + end +end diff --git a/lib/prism/middleware/session.rb b/lib/prism/middleware/session.rb new file mode 100644 index 0000000..93d7ac8 --- /dev/null +++ b/lib/prism/middleware/session.rb @@ -0,0 +1,40 @@ +module Prism + module Middleware + class Session + CookieName = 'prism.session'.freeze + + def initialize(app, secret:, cookie_name: CookieName, **options) + @app = app + @secret = secret + @cookie_name = cookie_name + @options = options + end + + def call(env) + request = Request.new(env) + loaded = Prism::Session.decode(request.cookies[@cookie_name], @secret) + session = Params.from(loaded) + env['prism.session'] = session + original = session.dup + + status, headers, body = @app.call(env) + + current = env['prism.session'] + if current != original + write_cookie(headers, Prism::Session.encode(current.to_h, @secret)) + end + [status, headers, body] + end + + private + + def write_cookie(headers, value) + pieces = ["#{@cookie_name}=#{value}", 'Path=/', 'HttpOnly', 'SameSite=Lax'] + pieces << "Max-Age=#{@options[:max_age]}" if @options[:max_age] + line = pieces.join('; ') + existing = headers['Set-Cookie'] + headers['Set-Cookie'] = existing ? "#{existing}\n#{line}" : line + end + end + end +end