Skip to content

Commit

Permalink
Handle invalid templates
Browse files Browse the repository at this point in the history
  • Loading branch information
paul committed Dec 7, 2011
1 parent c939ef3 commit 0ca75b7
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 44 deletions.
10 changes: 7 additions & 3 deletions lib/uri_template.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
require "uri_template/version"
require "uri_template/parser"
require "uri_template/transformer"
__dir__ = File.dirname(__FILE__)
require __dir__ + "/uri_template/version"
require __dir__ + "/uri_template/parser"
require __dir__ + "/uri_template/transformer"

class URITemplate
class ParseError < StandardError; end

def initialize(uri_template)
@uri_template = uri_template
tree = Parser.new.parse(@uri_template)
@template = Transform.new.apply(tree)
rescue Parslet::ParseFailed => ex
raise ParseError, "invalid template: #{uri_template}"
end

def expand(params)
Expand Down
80 changes: 42 additions & 38 deletions lib/uri_template/parser.rb
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
class UriTemplate::Parser < Parslet::Parser
require 'parslet'

rule(:uri_template) do
uri_element.repeat(1)
end
class URITemplate
class Parser < Parslet::Parser

rule(:uri_element) do
expansion | uri_part
end
rule(:uri_template) do
uri_element.repeat(1)
end

rule(:expansion) do
str('{') >> operator.maybe.as(:operator) >> (var_list | var) >> str('}')
end
rule(:uri_element) do
expansion | uri_part
end

rule(:operator) do
str('?')
end
rule(:expansion) do
str('{') >> operator.maybe.as(:operator) >> (var_list | var) >> str('}')
end

rule(:var_list) do
(var >> ( str(",") >> var ).repeat(1)).as(:list)
end
rule(:operator) do
str('?')
end

rule(:var) do
match('[a-zA-Z0-9]').repeat(1).as(:var)
end
rule(:var_list) do
(var >> ( str(",") >> var ).repeat(1)).as(:list)
end

rule(:uri_part) do
(unreserved | reserved | pct_encoded).repeat(1).as(:string)
end
rule(:var) do
match('[a-zA-Z0-9]').repeat(1).as(:var)
end

rule(:unreserved) do
alphanumeric | match("[-._~]")
end
rule(:uri_part) do
(unreserved | reserved | pct_encoded).repeat(1).as(:string)
end

rule(:alphanumeric) do
match('[A-Za-z0-9]')
end
rule(:unreserved) do
alphanumeric | match("[-._~]")
end

rule(:reserved) do
match("[:/?#\\[\\]@!$&'()*+,;=]")
end
rule(:alphanumeric) do
match('[A-Za-z0-9]')
end

rule(:pct_encoded) do
str('%') >> hex >> hex
end
rule(:reserved) do
match("[:/?#\\[\\]@!$&'()*+,;=]")
end

rule(:hex) do
match('[a-fA-F0-9]')
end
rule(:pct_encoded) do
str('%') >> hex >> hex
end

rule(:hex) do
match('[a-fA-F0-9]')
end

root(:uri_template)
root(:uri_template)

end
end

10 changes: 7 additions & 3 deletions lib/uri_template/transformer.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
class UriTemplate::Transformer < Parslet::Transformer
require 'parslet'

rule(:string => simple(:st)) { st.to_s }
class URITemplate
class Transformer < Parslet::Transform

rule(:var => simple(:var)) { var.to_s }
rule(:string => simple(:st)) { st.to_s }

rule(:var => simple(:var)) { var.to_s }

end
end

36 changes: 36 additions & 0 deletions spec/errors_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'rspec'
require File.expand_path(File.dirname(__FILE__) + "/../lib/uri_template")

describe URITemplate do

describe "with good uris" do

good = [
"http://example.com/",
"http://example.com/{foo}",
"http://example.com/search{?q}",
"http://example.com/search{?q,list}"
]

good.each do |tmpl|
it "should parse #{tmpl.inspect}" do
lambda { URITemplate.new(tmpl) }.should_not raise_error(URITemplate::ParseError)
end
end
end

describe "with invaldi uris" do

bad = [
"http://example.com/{",
"http://example.com/{^foo}"
]

bad.each do |tmpl|
it "should not parse #{tmpl.inspect}" do
lambda { URITemplate.new(tmpl) }.should raise_error(URITemplate::ParseError)
end
end
end
end

1 change: 1 addition & 0 deletions uri_template.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ Gem::Specification.new do |gem|

gem.add_dependency "parslet"

gem.add_development_dependency "rspec"
end

0 comments on commit 0ca75b7

Please sign in to comment.