From ebeda47cc4ca88359dfb9f201e2b2fb62f107fd7 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kryukov Date: Sat, 6 Apr 2024 17:28:48 +0300 Subject: [PATCH] Pass headers to body parsers --- CHANGELOG.md | 11 +++++++++++ lib/skooma/body_parsers.rb | 4 ++-- lib/skooma/env_mapper.rb | 11 ++++++++++- lib/skooma/instance.rb | 16 ++++++++-------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e15f7e..97f0c4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning]. ## [Unreleased] +### Changed + +- BREAKING CHANGE: Pass `headers` parameter to registered `BodyParsers`. ([@skryukov]) + + ```ruby + # Before: + Skooma::BodyParsers.register("application/xml", ->(body) { Hash.from_xml(body) }) + # After: + Skooma::BodyParsers.register("application/xml", ->(body, headers:) { Hash.from_xml(body) }) + ``` + ## [0.2.3] - 2024-01-18 ### Added diff --git a/lib/skooma/body_parsers.rb b/lib/skooma/body_parsers.rb index cd5c4d3..075c3fb 100644 --- a/lib/skooma/body_parsers.rb +++ b/lib/skooma/body_parsers.rb @@ -3,7 +3,7 @@ module Skooma module BodyParsers class << self - DEFAULT_PARSER = ->(body) { body } + DEFAULT_PARSER = ->(body, **_options) { body } def [](media_type) parsers[media_type.to_s.strip.downcase] || DEFAULT_PARSER @@ -20,7 +20,7 @@ def register(*media_types, parser) self.parsers = {} module JSONParser - def self.call(body) + def self.call(body, **_options) JSON.parse(body) rescue JSON::ParserError body diff --git a/lib/skooma/env_mapper.rb b/lib/skooma/env_mapper.rb index a6577dc..4212d56 100644 --- a/lib/skooma/env_mapper.rb +++ b/lib/skooma/env_mapper.rb @@ -23,10 +23,19 @@ def map_request(env) { "query" => env["rack.request.query_string"] || env["QUERY_STRING"], "headers" => env.select { |k, _| k.start_with?("HTTP_") || PLAIN_HEADERS.include?(k) }.transform_keys { |k| k.sub(REGEXP_HTTP, "").split("_").map(&:capitalize).join("-") }, - "body" => env["RAW_POST_DATA"] + "body" => env["RAW_POST_DATA"] || read_rack_input(env["rack.input"]) } end + def read_rack_input(input) + return nil unless input.respond_to?(:rewind) + + input.rewind + raw_input = input.read + input.rewind + raw_input + end + def map_response(response) status, headers, body = response.to_a full_body = +"" diff --git a/lib/skooma/instance.rb b/lib/skooma/instance.rb index b495c8f..23e4d36 100644 --- a/lib/skooma/instance.rb +++ b/lib/skooma/instance.rb @@ -63,16 +63,16 @@ def parse_value(value) data = {} data["status"] = JSONSkooma::JSONNode.new(value.fetch("status"), key: "status", parent: self) data["headers"] = Headers.new(value.fetch("headers", {}), key: "headers", parent: self) - body_value = parse_body(value["body"], data["headers"]&.[]("Content-Type")) + body_value = parse_body(value["body"], data["headers"]) data["body"] = Attribute.new(body_value, key: "body", parent: self) ["object", data] end - def parse_body(body, content_type) + def parse_body(body, headers) return nil unless body - parser = BodyParsers[content_type&.split(";")&.first] - parser ? parser.call(body) : body + parser = BodyParsers[headers["Content-Type"]&.value&.split(";")&.first] + parser ? parser.call(body, headers: headers) : body end end @@ -83,16 +83,16 @@ def parse_value(value) data = {} data["query"] = Attribute.new(value.fetch("query", ""), key: "query", parent: self) data["headers"] = Headers.new(value.fetch("headers", {}), key: "headers", parent: self) - body_value = parse_body(value["body"], data["headers"]&.[]("Content-Type")) + body_value = parse_body(value["body"], data["headers"]) data["body"] = Attribute.new(body_value, key: "body", parent: self) ["object", data] end - def parse_body(body, content_type) + def parse_body(body, headers) return nil unless body - parser = BodyParsers[content_type&.split(";")&.first] - parser ? parser.call(body) : body + parser = BodyParsers[headers["Content-Type"]&.value&.split(";")&.first] + parser ? parser.call(body, headers: headers) : body end end