Class: Protocol::Content::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/protocol/content/parser.rb,
lib/protocol/content/default.rb

Overview

Selects a content parser according to its media type.

Constant Summary collapse

DEFAULT =
build do |parser|
	json_parser = JSONParser.new
	parser.register(JSONParser::MEDIA_TYPE) do |input|
		json_parser.parse(input)
	end
	
	url_encoded_form_parser = Protocol::URL::FormData::Parser.new
	parser.register(Protocol::URL::FormData::Parser::MEDIA_TYPE) do |input, _media_type, &block|
		url_encoded_form_parser.parse(input, &block)
	rescue Protocol::URL::LimitError
		raise ContentTooLargeError
	end
	
	multipart_form_parser = Protocol::Multipart::FormData::Parser.new
	parser.register(Protocol::Multipart::FormData::Parser::MEDIA_TYPE) do |input, media_type, &block|
		if boundary = media_type.parameters["boundary"]
			multipart_form_parser.parse(input, boundary: boundary, &block)
		else
			raise ArgumentError, "Multipart media type is missing a boundary!"
		end
	rescue Protocol::Multipart::LimitError, Protocol::URL::LimitError
		raise ContentTooLargeError
	end
end

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeParser

Initialize an empty parser.



26
27
28
# File 'lib/protocol/content/parser.rb', line 26

def initialize
	@handlers = Protocol::Media::Map.new
end

Class Method Details

.build {|parser| ... } ⇒ Object

Build and freeze a parser.

Yields:

  • (parser)


19
20
21
22
23
# File 'lib/protocol/content/parser.rb', line 19

def self.build
	parser = self.new
	yield parser
	return parser.freeze
end

.defaultObject

The default parser for common media types.



42
43
44
# File 'lib/protocol/content/default.rb', line 42

def self.default
	return DEFAULT
end

Instance Method Details

#freezeObject

Freeze the parser and its handler registry.



69
70
71
72
# File 'lib/protocol/content/parser.rb', line 69

def freeze
	@handlers.freeze
	super
end

#parse(media_type, input, &block) ⇒ Object

Parse content using the handler matching its media type.



57
58
59
60
61
62
63
64
65
# File 'lib/protocol/content/parser.rb', line 57

def parse(media_type, input, &block)
	media_type = Protocol::Media::Type.for(media_type)
	
	if media_type && handler = @handlers[media_type]
		return handler.call(input, media_type, &block)
	end
	
	raise UnsupportedMediaTypeError, media_type
end

#register(media_range, handler = nil, &block) ⇒ Object

Register a handler for a media type or range.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/protocol/content/parser.rb', line 37

def register(media_range, handler = nil, &block)
	if handler && block
		raise ArgumentError, "Provide either a handler or a block!"
	end
	
	handler ||= block
	
	unless handler&.respond_to?(:call)
		raise ArgumentError, "A content handler must respond to #call!"
	end
	
	@handlers[media_range] = handler
	return handler
end