rack-client 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +2 -2
- data/README.textile +2 -2
- data/Rakefile +11 -5
- data/demo/demo_spec.rb +3 -3
- data/lib/rack/client.rb +29 -25
- data/lib/rack/client/adapter.rb +6 -0
- data/lib/rack/client/adapter/base.rb +57 -0
- data/lib/rack/client/adapter/simple.rb +49 -0
- data/lib/rack/client/auth/abstract/challenge.rb +53 -0
- data/lib/rack/client/auth/basic.rb +57 -0
- data/lib/rack/client/auth/digest/challenge.rb +38 -0
- data/lib/rack/client/auth/digest/md5.rb +78 -0
- data/lib/rack/client/auth/digest/params.rb +10 -0
- data/lib/rack/client/body.rb +12 -0
- data/lib/rack/client/cache.rb +19 -0
- data/lib/rack/client/cache/cachecontrol.rb +195 -0
- data/lib/rack/client/cache/context.rb +95 -0
- data/lib/rack/client/cache/entitystore.rb +77 -0
- data/lib/rack/client/cache/key.rb +51 -0
- data/lib/rack/client/cache/metastore.rb +133 -0
- data/lib/rack/client/cache/options.rb +147 -0
- data/lib/rack/client/cache/request.rb +46 -0
- data/lib/rack/client/cache/response.rb +62 -0
- data/lib/rack/client/cache/storage.rb +43 -0
- data/lib/rack/client/cookie_jar.rb +17 -0
- data/lib/rack/client/cookie_jar/context.rb +59 -0
- data/lib/rack/client/cookie_jar/cookie.rb +59 -0
- data/lib/rack/client/cookie_jar/cookiestore.rb +36 -0
- data/lib/rack/client/cookie_jar/options.rb +43 -0
- data/lib/rack/client/cookie_jar/request.rb +15 -0
- data/lib/rack/client/cookie_jar/response.rb +16 -0
- data/lib/rack/client/cookie_jar/storage.rb +34 -0
- data/lib/rack/client/dual_band.rb +13 -0
- data/lib/rack/client/follow_redirects.rb +47 -20
- data/lib/rack/client/handler.rb +10 -0
- data/lib/rack/client/handler/em-http.rb +66 -0
- data/lib/rack/client/handler/excon.rb +50 -0
- data/lib/rack/client/handler/net_http.rb +85 -0
- data/lib/rack/client/handler/typhoeus.rb +62 -0
- data/lib/rack/client/headers.rb +49 -0
- data/lib/rack/client/parser.rb +18 -0
- data/lib/rack/client/parser/base.rb +25 -0
- data/lib/rack/client/parser/body_collection.rb +50 -0
- data/lib/rack/client/parser/context.rb +15 -0
- data/lib/rack/client/parser/json.rb +54 -0
- data/lib/rack/client/parser/middleware.rb +8 -0
- data/lib/rack/client/parser/request.rb +21 -0
- data/lib/rack/client/parser/response.rb +19 -0
- data/lib/rack/client/parser/yaml.rb +52 -0
- data/lib/rack/client/response.rb +9 -0
- data/lib/rack/client/version.rb +5 -0
- data/spec/apps/example.org.ru +47 -3
- data/spec/auth/basic_spec.rb +69 -0
- data/spec/auth/digest/md5_spec.rb +69 -0
- data/spec/cache_spec.rb +40 -0
- data/spec/cookie_jar_spec.rb +37 -0
- data/spec/endpoint_spec.rb +4 -13
- data/spec/follow_redirect_spec.rb +27 -0
- data/spec/handler/async_api_spec.rb +69 -0
- data/spec/handler/em_http_spec.rb +22 -0
- data/spec/handler/excon_spec.rb +7 -0
- data/spec/handler/net_http_spec.rb +8 -0
- data/spec/handler/sync_api_spec.rb +55 -0
- data/spec/handler/typhoeus_spec.rb +22 -0
- data/spec/middleware_helper.rb +37 -0
- data/spec/middleware_spec.rb +48 -5
- data/spec/parser/json_spec.rb +22 -0
- data/spec/parser/yaml_spec.rb +22 -0
- data/spec/server_helper.rb +72 -0
- data/spec/spec_helper.rb +17 -3
- metadata +86 -31
- data/lib/rack/client/auth.rb +0 -13
- data/lib/rack/client/http.rb +0 -77
- data/spec/auth_spec.rb +0 -22
- data/spec/core_spec.rb +0 -123
- data/spec/redirect_spec.rb +0 -12
data/History.txt
CHANGED
data/README.textile
CHANGED
@@ -14,8 +14,8 @@ h2. Rack responses
|
|
14
14
|
|
15
15
|
Rack::Client can be used to make HTTP requests to any type of server, not
|
16
16
|
just ones using Rack. However, when a request is made then a proper
|
17
|
-
Rack response (specifically a Rack::MockResponse) object is returned.
|
18
|
-
For Rubyists, this means you don't need to learn yet another interface
|
17
|
+
Rack response (specifically a Rack::MockResponse) object is returned.
|
18
|
+
For Rubyists, this means you don't need to learn yet another interface
|
19
19
|
and can just stick with Rack both on the server, test, and client side of
|
20
20
|
things.
|
21
21
|
|
data/Rakefile
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'rake'
|
2
3
|
require "rake/gempackagetask"
|
3
4
|
require "rake/clean"
|
4
5
|
require "spec/rake/spectask"
|
5
|
-
|
6
|
+
|
7
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
8
|
+
require 'rack/client/version'
|
6
9
|
|
7
10
|
Spec::Rake::SpecTask.new(:spec) do |t|
|
8
|
-
t.spec_files = FileList['spec
|
11
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
9
12
|
t.spec_opts = ['-c']
|
10
13
|
end
|
11
14
|
|
@@ -13,7 +16,7 @@ task :default => :spec
|
|
13
16
|
|
14
17
|
spec = Gem::Specification.new do |s|
|
15
18
|
s.name = "rack-client"
|
16
|
-
s.rubyforge_project = s.name
|
19
|
+
s.rubyforge_project = s.name
|
17
20
|
s.version = Rack::Client::VERSION
|
18
21
|
s.author = "Tim Carey-Smith"
|
19
22
|
s.email = "tim" + "@" + "spork.in"
|
@@ -23,8 +26,11 @@ spec = Gem::Specification.new do |s|
|
|
23
26
|
s.files = %w[History.txt LICENSE README.textile Rakefile] + Dir["lib/**/*"] + Dir["demo/**/*"]
|
24
27
|
s.test_files = Dir["spec/**/*"]
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
require 'bundler'
|
30
|
+
bundle = Bundler::Definition.from_gemfile("Gemfile")
|
31
|
+
bundle.dependencies.
|
32
|
+
select { |d| d.groups.include?(:runtime) }.
|
33
|
+
each { |d| s.add_dependency(d.name, d.version_requirements.to_s) }
|
28
34
|
end
|
29
35
|
|
30
36
|
Rake::GemPackageTask.new(spec) do |package|
|
data/demo/demo_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Demo, "/store resource" do
|
|
12
12
|
Rack::Client.new
|
13
13
|
# Demo::App.new
|
14
14
|
end
|
15
|
-
before(:all) { delete "http://localhost:9292/store" }
|
15
|
+
before(:all) { delete "http://localhost:9292/store" }
|
16
16
|
after { delete "http://localhost:9292/store" }
|
17
17
|
|
18
18
|
it "should return a 404 if a resource does not exist" do
|
@@ -28,8 +28,8 @@ describe Demo, "/store resource" do
|
|
28
28
|
last_response.status.should == 200
|
29
29
|
last_response.body.should == "strawberry"
|
30
30
|
get "http://localhost:9292/store/car"
|
31
|
-
last_response.status.should == 200
|
32
|
-
last_response.body.should == "lotus"
|
31
|
+
last_response.status.should == 200
|
32
|
+
last_response.body.should == "lotus"
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should be able to clear the store of all items" do
|
data/lib/rack/client.rb
CHANGED
@@ -1,37 +1,41 @@
|
|
1
|
-
unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__) + "/.."))
|
2
|
-
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/.."))
|
3
|
-
end
|
4
|
-
|
5
|
-
require 'rack'
|
6
|
-
require 'rack/test'
|
7
1
|
require 'forwardable'
|
2
|
+
require 'uri'
|
3
|
+
require 'rack'
|
8
4
|
|
9
5
|
module Rack
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
HTTP_METHODS = [:head, :get, :put, :post, :delete]
|
14
|
-
|
6
|
+
module Client
|
7
|
+
include Forwardable
|
8
|
+
|
15
9
|
class << self
|
16
10
|
extend Forwardable
|
17
|
-
def_delegators :new,
|
18
|
-
end
|
19
|
-
|
20
|
-
def run(*args, &block)
|
21
|
-
@ran = true
|
22
|
-
super(*args, &block)
|
11
|
+
def_delegators :new, :head, :get, :put, :post, :delete
|
23
12
|
end
|
24
13
|
|
25
|
-
def
|
26
|
-
run Rack::Client::
|
27
|
-
|
14
|
+
def self.new(*a, &block)
|
15
|
+
block ||= lambda { run Rack::Client::Handler::NetHTTP }
|
16
|
+
Rack::Client::Simple.new(Rack::Builder.app(&block), *a)
|
28
17
|
end
|
29
|
-
alias app to_app
|
30
18
|
end
|
31
19
|
end
|
32
20
|
|
33
|
-
|
21
|
+
require 'rack/client/version'
|
22
|
+
|
23
|
+
require 'rack/client/handler'
|
24
|
+
require 'rack/client/dual_band'
|
25
|
+
require 'rack/client/response'
|
26
|
+
require 'rack/client/headers'
|
27
|
+
|
28
|
+
require 'rack/client/adapter'
|
29
|
+
|
30
|
+
require 'rack/client/follow_redirects'
|
31
|
+
require 'rack/client/auth/abstract/challenge'
|
32
|
+
require 'rack/client/auth/basic'
|
33
|
+
require 'rack/client/auth/digest/challenge'
|
34
|
+
require 'rack/client/auth/digest/params'
|
35
|
+
require 'rack/client/auth/digest/md5'
|
36
|
+
|
37
|
+
require 'rack/client/cache'
|
38
|
+
|
39
|
+
require 'rack/client/cookie_jar'
|
34
40
|
|
35
|
-
require 'client/
|
36
|
-
require 'client/auth'
|
37
|
-
require 'client/follow_redirects'
|
41
|
+
require 'rack/client/parser'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
class Base
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
def_delegator :@app, :call
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
%w[ options get head post put delete trace connect ].each do |method|
|
13
|
+
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
14
|
+
def #{method}(url, headers = {}, body = nil)
|
15
|
+
if block_given?
|
16
|
+
call(build_env('#{method.upcase}', url, headers, body)) {|tuple| yield *tuple }
|
17
|
+
else
|
18
|
+
return *call(build_env('#{method.upcase}', url, headers, body))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_env(request_method, url, headers = {}, body = nil)
|
25
|
+
env = Headers.new(headers).to_env
|
26
|
+
|
27
|
+
env.update 'REQUEST_METHOD' => request_method
|
28
|
+
|
29
|
+
env['CONTENT_TYPE'] ||= 'application/x-www-form-urlencoded'
|
30
|
+
|
31
|
+
uri = URI.parse(url)
|
32
|
+
|
33
|
+
path_info = uri.path.empty? ? '/' : uri.path
|
34
|
+
path_info += '?' + uri.query unless uri.query.nil? || uri.query.empty?
|
35
|
+
|
36
|
+
env.update 'PATH_INFO' => path_info
|
37
|
+
env.update 'REQUEST_URI' => uri.to_s
|
38
|
+
env.update 'SERVER_NAME' => uri.host
|
39
|
+
env.update 'SERVER_PORT' => uri.port
|
40
|
+
env.update 'SCRIPT_NAME' => ''
|
41
|
+
|
42
|
+
input = case body
|
43
|
+
when nil then StringIO.new
|
44
|
+
when String then StringIO.new(body)
|
45
|
+
end
|
46
|
+
|
47
|
+
env.update 'rack.input' => input
|
48
|
+
env.update 'rack.errors' => StringIO.new
|
49
|
+
env.update 'rack.url_scheme' => uri.scheme
|
50
|
+
|
51
|
+
env.update 'HTTPS' => env["rack.url_scheme"] == "https" ? "on" : "off"
|
52
|
+
|
53
|
+
env
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
class Simple < Base
|
4
|
+
|
5
|
+
def initialize(app, url = nil)
|
6
|
+
super(app)
|
7
|
+
@base_uri = URI.parse(url) unless url.nil?
|
8
|
+
end
|
9
|
+
|
10
|
+
%w[ options get head delete trace ].each do |method|
|
11
|
+
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
12
|
+
def #{method}(url, headers = {}, query_or_params = nil)
|
13
|
+
headers, query_or_params = {}, headers if query_or_params.nil?
|
14
|
+
query_hash = Hash === query_or_params ? query_or_params : Utils.build_query(query_or_params)
|
15
|
+
|
16
|
+
uri = URI.parse(url)
|
17
|
+
uri.query = Utils.build_query(Utils.parse_query(uri.query).merge(query_hash))
|
18
|
+
|
19
|
+
if block_given?
|
20
|
+
super(uri.to_s, headers) {|*tuple| yield Response.new(*tuple) }
|
21
|
+
else
|
22
|
+
return Response.new(*super(uri.to_s, headers))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
|
28
|
+
%w[ post put ].each do |method|
|
29
|
+
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
|
30
|
+
def #{method}(url, headers = {}, body_or_params = nil)
|
31
|
+
headers, body_or_params = {}, headers if body_or_params.nil?
|
32
|
+
body = Hash === body_or_params ? Utils.build_query(body_or_params) : body_or_params
|
33
|
+
|
34
|
+
if block_given?
|
35
|
+
super(url, headers, body) {|*tuple| yield Response.new(*tuple) }
|
36
|
+
else
|
37
|
+
return Response.new(*super(url, headers, body))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_env(request_method, url, headers = {}, body = nil)
|
44
|
+
uri = @base_uri.nil? ? URI.parse(url) : @base_uri + url
|
45
|
+
super(request_method, uri.to_s, headers, body)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
module Auth
|
4
|
+
module Abstract
|
5
|
+
class Challenge
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@request, :request_method, :path
|
9
|
+
def_delegators :@response, :status, :headers
|
10
|
+
|
11
|
+
def initialize(request, response)
|
12
|
+
@request, @response = request, response
|
13
|
+
end
|
14
|
+
|
15
|
+
def required?
|
16
|
+
status == 401
|
17
|
+
end
|
18
|
+
|
19
|
+
def unspecified?
|
20
|
+
scheme.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def www_authenticate
|
24
|
+
@www_authenticate ||= headers.detect {|h,_| h =~ /^WWW-AUTHENTICATE$/i }
|
25
|
+
end
|
26
|
+
|
27
|
+
def parts
|
28
|
+
@parts ||= www_authenticate if www_authenticate
|
29
|
+
end
|
30
|
+
|
31
|
+
def scheme
|
32
|
+
@scheme ||= www_authenticate.last[/^(\w+)/, 1].downcase.to_sym if www_authenticate
|
33
|
+
end
|
34
|
+
|
35
|
+
def nonce
|
36
|
+
@nonce ||= Rack::Auth::Digest::Nonce.parse(params['nonce'])
|
37
|
+
end
|
38
|
+
|
39
|
+
def params
|
40
|
+
@params ||= Rack::Auth::Digest::Params.parse(parts.last)
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(sym)
|
44
|
+
if params.has_key? key = sym.to_s
|
45
|
+
return params[key]
|
46
|
+
end
|
47
|
+
super
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
module Auth
|
4
|
+
class Basic
|
5
|
+
include Rack::Client::DualBand
|
6
|
+
|
7
|
+
def initialize(app, username, password)
|
8
|
+
@app, @username, @password = app, username, password
|
9
|
+
end
|
10
|
+
|
11
|
+
def sync_call(env)
|
12
|
+
request = Rack::Request.new(env)
|
13
|
+
response = Response.new(*@app.call(env))
|
14
|
+
challenge = Basic::Challenge.new(request, response)
|
15
|
+
|
16
|
+
if challenge.required? && (challenge.unspecified? || challenge.basic?)
|
17
|
+
return authorized_call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
response.finish
|
21
|
+
end
|
22
|
+
|
23
|
+
def async_call(env, &b)
|
24
|
+
@app.call(env) do |response_parts|
|
25
|
+
request = Rack::Request.new(env)
|
26
|
+
response = Response.new(*response_parts)
|
27
|
+
challenge = Basic::Challenge.new(request, response)
|
28
|
+
|
29
|
+
if challenge.required? && (challenge.unspecified? || challenge.basic?)
|
30
|
+
authorized_call(env, &b)
|
31
|
+
else
|
32
|
+
yield response.finish
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def authorized_call(env, &b)
|
38
|
+
@app.call(env.merge(auth_header), &b)
|
39
|
+
end
|
40
|
+
|
41
|
+
def auth_header
|
42
|
+
{'HTTP_AUTHORIZATION' => "Basic #{encoded_login}"}
|
43
|
+
end
|
44
|
+
|
45
|
+
def encoded_login
|
46
|
+
["#{@username}:#{@password}"].pack("m*")
|
47
|
+
end
|
48
|
+
|
49
|
+
class Challenge < Abstract::Challenge
|
50
|
+
def basic?
|
51
|
+
:basic == scheme
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
module Auth
|
4
|
+
module Digest
|
5
|
+
class Challenge < Abstract::Challenge
|
6
|
+
def initialize(request, response, realm, username, password)
|
7
|
+
super(request, response)
|
8
|
+
@realm, @username, @password = realm, username, password
|
9
|
+
end
|
10
|
+
|
11
|
+
def digest?
|
12
|
+
:digest == scheme
|
13
|
+
end
|
14
|
+
|
15
|
+
def cnonce
|
16
|
+
@cnonce ||= Rack::Auth::Digest::Nonce.new.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def response(nc)
|
20
|
+
H([ A1(), nonce, nc, cnonce, qop, A2() ] * ':')
|
21
|
+
end
|
22
|
+
|
23
|
+
def A1
|
24
|
+
H([ @username, @realm, @password ] * ':')
|
25
|
+
end
|
26
|
+
|
27
|
+
def A2
|
28
|
+
H([ request_method, path ] * ':')
|
29
|
+
end
|
30
|
+
|
31
|
+
def H(data)
|
32
|
+
::Digest::MD5.hexdigest(data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Rack
|
2
|
+
module Client
|
3
|
+
module Auth
|
4
|
+
module Digest
|
5
|
+
class MD5 < Rack::Auth::Digest::MD5
|
6
|
+
include Rack::Client::DualBand
|
7
|
+
|
8
|
+
def initialize(app, realm, username, password, options = {})
|
9
|
+
@app, @realm, @username, @password = app, realm, username, password
|
10
|
+
@nc = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def sync_call(env)
|
14
|
+
request = Rack::Request.new(env)
|
15
|
+
response = Response.new(*@app.call(env))
|
16
|
+
challenge = Digest::Challenge.new(request, response, @realm, @username, @password)
|
17
|
+
|
18
|
+
if challenge.required? && challenge.digest? && valid?(challenge)
|
19
|
+
return @app.call(env.merge(authorization(challenge)))
|
20
|
+
end
|
21
|
+
|
22
|
+
response.finish
|
23
|
+
end
|
24
|
+
|
25
|
+
def async_call(env)
|
26
|
+
@app.call(env) do |response_parts|
|
27
|
+
request = Rack::Request.new(env)
|
28
|
+
response = Response.new(*response_parts)
|
29
|
+
challenge = Digest::Challenge.new(request, response, @realm, @username, @password)
|
30
|
+
|
31
|
+
if challenge.required? && challenge.digest? && valid?(challenge)
|
32
|
+
@app.call(env.merge(authorization(challenge))) {|response_parts| yield response_parts }
|
33
|
+
else
|
34
|
+
@app.call(env) {|response_parts| yield response_parts }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid?(challenge)
|
40
|
+
valid_opaque?(challenge) && valid_nonce?(challenge)
|
41
|
+
end
|
42
|
+
|
43
|
+
def valid_opaque?(challenge)
|
44
|
+
!(challenge.opaque.nil? || challenge.opaque.empty?)
|
45
|
+
end
|
46
|
+
|
47
|
+
def valid_nonce?(challenge)
|
48
|
+
challenge.nonce.valid?
|
49
|
+
end
|
50
|
+
|
51
|
+
def authorization(challenge)
|
52
|
+
return 'HTTP_AUTHORIZATION' => "Digest #{params_for(challenge)}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def params_for(challenge)
|
56
|
+
nc = next_nc
|
57
|
+
|
58
|
+
Rack::Auth::Digest::Params.new do |params|
|
59
|
+
params['username'] = @username
|
60
|
+
params['realm'] = @realm
|
61
|
+
params['nonce'] = challenge.nonce.to_s
|
62
|
+
params['uri'] = challenge.path
|
63
|
+
params['qop'] = challenge.qop
|
64
|
+
params['nc'] = nc
|
65
|
+
params['cnonce'] = challenge.cnonce
|
66
|
+
params['response'] = challenge.response(nc)
|
67
|
+
params['opaque'] = challenge.opaque
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def next_nc
|
72
|
+
sprintf("%08x", @nc += 1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|