Created
March 5, 2013 08:13
-
-
Save kapkaev/5088751 to your computer and use it in GitHub Desktop.
Faraday::Request::DigestAuth
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'faraday' | |
require 'net/http/digest_auth' | |
module Faraday | |
# Public: A Faraday middleware to use digest authentication. Since order of | |
# middlewares do care, it should be the first one of the Request middlewares | |
# in order to work properly (due to how digest authentication works). | |
# | |
# If some requests using the connection don't need to use digest auth you | |
# don't have to worry, the middleware will do nothing. | |
# | |
# It uses Net::HTTP::DigestAuth to generate the authorization header but it | |
# should work with any adapter. | |
# | |
# Examples: | |
# | |
# connection = Faraday.new(...) do |connection| | |
# connection.request :digest, USER, PASSWORD | |
# end | |
# | |
# # You can also use it later with a connection: | |
# connection.digest_auth('USER', 'PASSWORD') | |
# | |
class Request::DigestAuth < Faraday::Middleware | |
# Public: Initializes a DigestAuth. | |
# | |
# app - The Faraday app. | |
# user - A String with the user to authentication the connection. | |
# password - A String with the password to authentication the connection. | |
def initialize(app, user, password) | |
super(app) | |
@user, @password = user, password | |
end | |
# Public: Sends a first request with an empty body to get the | |
# authentication headers and then send the same request with the body and | |
# authorization header. | |
# | |
# env - A Hash with the request environment. | |
# | |
# Returns a Faraday::Response. | |
def call(env) | |
response = handshake(env) | |
return response unless response.status == 401 | |
env[:request_headers]['Authorization'] = header(response) | |
@app.call(env) | |
end | |
private | |
# Internal: Sends the the request with an empry body. | |
# | |
# env - A Hash with the request environment. | |
# | |
# Returns a Faraday::Response. | |
def handshake(env) | |
env_without_body = env.dup | |
env_without_body.delete(:body) | |
@app.call(env_without_body) | |
end | |
# Internal: Builds the authorization header with the authentication data. | |
# | |
# response - A Faraday::Response with the authenticate headers. | |
# | |
# Returns a String with the DigestAuth header. | |
def header(response) | |
uri = response.env[:url] | |
uri.user = @user | |
uri.password = @password | |
realm = response.headers['www-authenticate'] | |
method = response.env[:method].to_s.upcase | |
Net::HTTP::DigestAuth.new.auth_header(uri, realm, method) | |
end | |
end | |
class Connection | |
# Public: Adds the digest auth middleware at the top and sets the user and | |
# password. | |
# | |
# user - A String with the user. | |
# password - A String with the password. | |
# | |
def digest_auth(user, password) | |
self.builder.insert(0, Faraday::Request::DigestAuth, user, password) | |
end | |
end | |
end | |
# Register the middleware as a Request middleware with the name :digest | |
Faraday.register_middleware :request, digest: Faraday::Request::DigestAuth |
Thanks!
Actually, this seems a copy of hyperclient's implementation (but without the tests): See codegram/hyperclient@a47d7db and codegram/hyperclient@e443018#diff-05401ebefab536882f566b668412c798L2
I made a PR bhaberer/faraday-digestauth#6 acknowledging the origins of the gem and porting tests.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for writing this, it was super handy.
I went ahead and made this into a gem and upped it to Rubygems.
I added you as an author in the gemspec, but let me know if you want added to the repo or made a gem owner.