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.



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

def initialize
	@handlers = {}
end

Class Method Details

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

Build and freeze a parser.

Yields:

  • (parser)


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

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.



71
72
73
74
75
76
# File 'lib/protocol/content/parser.rb', line 71

def freeze
	return self if self.frozen?
	
	@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
66
67
# File 'lib/protocol/content/parser.rb', line 57

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

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

Register a handler for a media type.



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

def register(media_type, 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
	
	media_type = Protocol::Media::Type.for(media_type)
	@handlers[media_type.name] = handler
	return handler
end