Class: AtProto::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/atproto_client/client.rb

Overview

The Client class handles authenticated HTTP requests to the AT Protocol services with DPoP token support and automatic token refresh capabilities.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_token:, refresh_token:, private_key:, refresh_token_url: 'https://bsky.social') ⇒ Client

Initializes a new AT Protocol client

Parameters:

  • access_token (String)

    The initial access token for authentication

  • refresh_token (String)

    The refresh token for renewing access tokens

  • private_key (OpenSSL::PKey::EC)

    The EC private key used for DPoP token signing (required)

  • refresh_token_url (String) (defaults to: 'https://bsky.social')

    The base URL for token refresh requests

Raises:

  • (ArgumentError)

    If private_key is not provided or not an OpenSSL::PKey::EC instance



19
20
21
22
23
24
25
# File 'lib/atproto_client/client.rb', line 19

def initialize(access_token:, refresh_token:, private_key:, refresh_token_url: 'https://bsky.social')
  @access_token = access_token
  @refresh_token = refresh_token
  @refresh_token_url = refresh_token_url
  @dpop_handler = DpopHandler.new(private_key, access_token)
  @token_mutex = Mutex.new
end

Instance Attribute Details

#access_tokenString (readonly)

The current access token for authentication

Returns:

  • (String)

    the current value of access_token



8
9
10
# File 'lib/atproto_client/client.rb', line 8

def access_token
  @access_token
end

#dpop_handlerDpopHandler (readonly)

The handler for DPoP token operations

Returns:



8
9
10
# File 'lib/atproto_client/client.rb', line 8

def dpop_handler
  @dpop_handler
end

#refresh_tokenString (readonly)

The current refresh token for renewing access

Returns:

  • (String)

    the current value of refresh_token



8
9
10
# File 'lib/atproto_client/client.rb', line 8

def refresh_token
  @refresh_token
end

Instance Method Details

#private_key=(private_key) ⇒ Object

Sets a new private key for DPoP token signing

Parameters:

  • private_key (OpenSSL::PKey::EC)

    The EC private key to use for signing DPoP tokens (required)

Raises:

  • (ArgumentError)

    If private_key is not an OpenSSL::PKey::EC instance



31
32
33
# File 'lib/atproto_client/client.rb', line 31

def private_key=(private_key)
  @dpop_handler = @dpop_handler.new(private_key, @access_token)
end

#request(method, url, params: {}, body: nil) ⇒ Net::HTTPResponse

Makes an authenticated HTTP request with automatic token refresh

Parameters:

  • method (Symbol)

    The HTTP method to use (:get, :post, etc.)

  • url (String)

    The URL to send the request to

  • params (Hash) (defaults to: {})

    Optional query parameters

  • body (Hash, nil) (defaults to: nil)

    Optional request body

Returns:

  • (Net::HTTPResponse)

    The HTTP response

Raises:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/atproto_client/client.rb', line 46

def request(method, url, params: {}, body: nil)
  retries = 0
  begin
    uri = URI(url)
    uri.query = URI.encode_www_form(params) if params.any?
    @dpop_handler.make_request(
      uri.to_s,
      method,
      headers: { 'Authorization' => "DPoP #{@access_token}" },
      body: body
    )
  rescue TokenExpiredError => e
    raise e unless retries.zero? && @refresh_token

    retries += 1
    refresh_access_token!
    retry
  end
end