Skip to content

Commit

Permalink
Initial migration of code.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Jan 24, 2025
1 parent 3df19c7 commit 30759d7
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
66 changes: 66 additions & 0 deletions lib/protocol/http/media_types.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2016-2024, by Samuel Williams.

module Protocol
module HTTP
class MediaTypes
WILDCARD = "*/*".freeze

def initialize
@map = {}
end

def freeze
return self if frozen?

@map.freeze
@map.each_value(&:freeze)

return super
end

# Given a list of content types (e.g. from browser_preferred_content_types), return the best converter. Media types can be an array of MediaRange or String values.
def for(media_ranges)
media_ranges.each do |media_range|
range_string = media_range.range_string

if object = @map[range_string]
return object
end
end

return nil
end

def []= media_range, object
@map[media_range] = object
end

def [] media_range
@map[media_range]
end

# Add a converter to the collection. A converter can be anything that responds to #content_type. Objects will be considered in the order they are added, subsequent objects cannot override previously defined media types. `object` must respond to #split('/', 2) which should give the type and subtype.
def << object
media_range = object.media_range

# We set the default if not specified already:
@map[WILDCARD] = object if @map.empty?

type = media_range.type
if type != "*"
@map["#{type}/*"] ||= object

subtype = media_range.subtype
if subtype != "*"
@map["#{type}/#{subtype}"] ||= object
end
end

return self
end
end
end
end
71 changes: 71 additions & 0 deletions test/protocol/http/media_types.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2016-2024, by Samuel Williams.

require "protocol/http/accept/media_types"
require "protocol/http/accept/media_types/map"
require "protocol/http/accept/content_type"

describe Protocol::HTTP::MediaTypes do
let(:converter) do
Struct.new(:content_type) do
def split(*args)
self.content_type.split(*args)
end
end
end

let(:text_html_converter) {converter.new("text/html")}

let(:text_plain_content_type) {Protocol::HTTP::Accept::ContentType.new("text", "plain", charset: "utf-8")}
let(:text_plain_converter) {converter.new(text_plain_content_type)}

let(:map) {subject.new}

it "should give the correct converter when specified completely" do
map << text_html_converter
map << text_plain_converter

media_types = Protocol::HTTP::Accept::MediaTypes.parse("text/plain, text/*, */*")
expect(map.for(media_types).first).to be == text_plain_converter

media_types = Protocol::HTTP::Accept::MediaTypes.parse("text/html, text/*, */*")
expect(map.for(media_types).first).to be == text_html_converter
end

it "should match the wildcard subtype converter" do
map << text_html_converter
map << text_plain_converter

media_types = Protocol::HTTP::Accept::MediaTypes.parse("text/*, */*")
expect(map.for(media_types).first).to be == text_html_converter

media_types = Protocol::HTTP::Accept::MediaTypes.parse("*/*")
expect(map.for(media_types).first).to be == text_html_converter
end

it "should fail to match if no media types match" do
map << text_plain_converter

expect(map.for(["application/json"])).to be_nil
end

it "should fail to match if no media types specified" do
expect(map.for(["text/*", "*/*"])).to be_nil
end

it "should freeze converters" do
map << text_html_converter

map.freeze

expect(text_html_converter).to be(:frozen?)
end

it "should assign and retrive media ranges" do
map["*/*"] = :test

expect(map["*/*"]).to be == :test
end
end

0 comments on commit 30759d7

Please sign in to comment.