From 603be3ff5be1c256070ed348c5413756ca47a15e Mon Sep 17 00:00:00 2001 From: Kanezoh Date: Sat, 1 Jan 2022 21:20:07 +0900 Subject: [PATCH] add auth parser --- spec/www_authenticate_parser_spec.cr | 35 +++++++++++ src/mechanize/http/agent.cr | 2 +- src/mechanize/http/auth_challenge.cr | 10 ++-- src/mechanize/http/www_authenticate_parser.cr | 58 +++++++++---------- 4 files changed, 71 insertions(+), 34 deletions(-) diff --git a/spec/www_authenticate_parser_spec.cr b/spec/www_authenticate_parser_spec.cr index 582c389..e9b7feb 100644 --- a/spec/www_authenticate_parser_spec.cr +++ b/spec/www_authenticate_parser_spec.cr @@ -30,4 +30,39 @@ describe "Mechanize HTTP Authentication test" do parser.scanner = StringScanner.new("realm=\"this site\"") parser.auth_param.should eq ["realm", "this site"] end + + it "test parse" do + expect = [Mechanize::HTTP::AuthChallenge.new("Basic", {"realm" => "foo", "qop" => "auth,auth-int"})] + + parser = Mechanize::HTTP::WWWAuthenticateParser.new + result = parser.parse("Basic realm=foo, qop=\"auth,auth-int\"") + result[0].scheme.should eq expect[0].scheme + result[0].params.should eq expect[0].params + end + + it "test_parse_without_comma_delimiter" do + expect = [challenge("Basic", {"realm" => "foo", "qop" => "auth,auth-int"})] + parser = Mechanize::HTTP::WWWAuthenticateParser.new + result = parser.parse("Basic realm=foo qop=\"auth,auth-int\"") + result[0].scheme.should eq expect[0].scheme + result[0].params.should eq expect[0].params + end + + it "test_parse_multiple" do + expect = [ + challenge("Basic", {"realm" => "foo"}), + challenge("Digest", {"realm" => "bar"}), + ] + + parser = Mechanize::HTTP::WWWAuthenticateParser.new + result = parser.parse("Basic realm=foo, Digest realm=bar") + result[0].scheme.should eq expect[0].scheme + result[0].params.should eq expect[0].params + result[1].scheme.should eq expect[1].scheme + result[1].params.should eq expect[1].params + end +end + +private def challenge(scheme, params) + Mechanize::HTTP::AuthChallenge.new(scheme, params) end diff --git a/src/mechanize/http/agent.cr b/src/mechanize/http/agent.cr index 9a4f687..83a661e 100644 --- a/src/mechanize/http/agent.cr +++ b/src/mechanize/http/agent.cr @@ -170,7 +170,7 @@ class Mechanize private def save_response_cookies(response, uri, page) if page.body =~ /Set-Cookie/ page.css("head meta[http-equiv=\"Set-Cookie\"]").each do |meta| - cookie = meta["content"].split(";") # [0] + cookie = meta["content"].split(";")[0] key, value = cookie.split("=") cookie = ::HTTP::Cookie.new(name: key, value: value) save_cookies(uri, [cookie]) diff --git a/src/mechanize/http/auth_challenge.cr b/src/mechanize/http/auth_challenge.cr index ae8f4ce..cf47ebd 100644 --- a/src/mechanize/http/auth_challenge.cr +++ b/src/mechanize/http/auth_challenge.cr @@ -5,14 +5,16 @@ class Mechanize class AuthChallenge property scheme : String? - property params : String? + property params : String? | Hash(String, String)? def initialize(scheme = nil, params = nil) + @scheme = scheme + @params = params end - # def [] param - # params[param] - # end + def [](param) + params[param] + end ## # Constructs an AuthRealm for this challenge diff --git a/src/mechanize/http/www_authenticate_parser.cr b/src/mechanize/http/www_authenticate_parser.cr index 13ef8e3..af207eb 100644 --- a/src/mechanize/http/www_authenticate_parser.cr +++ b/src/mechanize/http/www_authenticate_parser.cr @@ -18,15 +18,16 @@ class Mechanize # Parsers the header. Returns an Array of challenges as strings def parse(www_authenticate : String) - challenges = [Mechanize::HTTP::AuthChallenge] - scanner = StringScanner.new(www_authenticate) + challenges = [] of Mechanize::HTTP::AuthChallenge + @scanner = StringScanner.new(www_authenticate) loop do break if scanner.eos? - start = scanner.pos + start = scanner.offset challenge = Mechanize::HTTP::AuthChallenge.new scheme = auth_scheme + if scheme == "Negotiate" scan_comma_spaces end @@ -45,39 +46,38 @@ class Mechanize challenges << challenge next else - scheme.capitalize! + scheme = scheme.capitalize end - # next unless space - # params = {} + next unless space + params = Hash(String, String).new - # while true do - # pos = @scanner.pos - # name, value = auth_param + loop do + offset = scanner.offset + param = auth_param + if param + name, value = param + name = name.downcase if name =~ /^realm$/i + params[name] = value + else + challenge.params = params + challenges << challenge - # name.downcase! if name =~ /^realm$/i + if scanner.eos? + # challenge.raw = www_authenticate[start, scanner.offset] + break + end - # unless name then - # challenge.params = params - # challenges << challenge + scanner.offset = offset # rewind + # challenge.raw = www_authenticate[start, scanner.offset].sub(/(,+)? *$/, "") + challenge = nil # a token should be next, new challenge + break + end - # if @scanner.eos? then - # challenge.raw = www_authenticate[start, @scanner.pos] - # break - # end + spaces - # @scanner.pos = pos # rewind - # challenge.raw = www_authenticate[start, @scanner.pos].sub(/(,+)? *$/, '') - # challenge = nil # a token should be next, new challenge - # break - # else - # params[name] = value - # end - - # spaces - - # @scanner.scan(/(, *)+/) - # end + scanner.scan(/(, *)+/) + end end challenges