Class: MatrixSdk::Api
- Includes:
- Logging, Protocols::AS, Protocols::CS, Protocols::IS, Protocols::SS
- Defined in:
- lib/matrix_sdk/api.rb
Constant Summary collapse
- USER_AGENT =
"Ruby Matrix SDK v#{MatrixSdk::VERSION}"
- DEFAULT_HEADERS =
{ 'accept' => 'application/json', 'user-agent' => USER_AGENT }.freeze
Instance Attribute Summary collapse
-
#access_token ⇒ Object
Returns the value of attribute access_token.
-
#autoretry ⇒ Object
Returns the value of attribute autoretry.
-
#connection_address ⇒ Object
Returns the value of attribute connection_address.
-
#connection_port ⇒ Object
Returns the value of attribute connection_port.
-
#device_id ⇒ Object
Returns the value of attribute device_id.
-
#global_headers ⇒ Object
Returns the value of attribute global_headers.
-
#homeserver ⇒ Object
Returns the value of attribute homeserver.
-
#protocols ⇒ Object
readonly
Returns the value of attribute protocols.
-
#proxy_uri ⇒ Object
Returns the value of attribute proxy_uri.
-
#read_timeout ⇒ Object
Returns the value of attribute read_timeout.
-
#validate_certificate ⇒ Object
Returns the value of attribute validate_certificate.
-
#well_known ⇒ Object
readonly
Returns the value of attribute well_known.
Class Method Summary collapse
-
.new_for_domain(domain, target: :client, keep_wellknown: false, ssl: true, **params) ⇒ API
Create an API connection to a domain entry.
Instance Method Summary collapse
-
#initialize(homeserver, **params) ⇒ Api
constructor
A new instance of Api.
- #protocol?(protocol) ⇒ Boolean
- #request(method, api, path, **options) ⇒ Object
Methods included from Protocols::SS
Methods included from Protocols::IS
#identity_bulk_lookup, #identity_get_pubkey, #identity_lookup, #identity_pubkey_ephemeral_isvalid, #identity_pubkey_isvalid, #identity_status
Methods included from Protocols::CS
#add_user_tag, #allowed_login_methods, #ban_user, #client_api_unstable_features, #client_api_versions, #create_filter, #create_room, #delete_device, #forget_room, #get_account_data, #get_avatar_url, #get_device, #get_devices, #get_display_name, #get_download_url, #get_filter, #get_joined_rooms, #get_membership, #get_profile, #get_public_rooms, #get_room_account_data, #get_room_aliases, #get_room_avatar, #get_room_creation_info, #get_room_encryption_settings, #get_room_guest_access, #get_room_history_visibility, #get_room_id, #get_room_join_rules, #get_room_members, #get_room_messages, #get_room_name, #get_room_pinned_events, #get_room_power_levels, #get_room_server_acl, #get_room_state, #get_room_topic, #get_user_tags, #invite_user, #join_room, #keys_query, #kick_user, #leave_room, #login, #logout, #media_upload, #redact_event, #register, #remove_room_alias, #remove_user_tag, #send_content, #send_emote, #send_location, #send_message, #send_message_event, #send_notice, #send_state_event, #set_account_data, #set_avatar_url, #set_device, #set_display_name, #set_membership, #set_room_account_data, #set_room_alias, #set_room_avatar, #set_room_encryption_settings, #set_room_guest_access, #set_room_history_visibility, #set_room_join_rules, #set_room_name, #set_room_pinned_events, #set_room_power_levels, #set_room_server_acl, #set_room_topic, #sync, #unban_user, #username_available?, #whoami?
Methods included from Protocols::AS
Methods included from Logging
Constructor Details
#initialize(homeserver, **params) ⇒ Api
Returns a new instance of Api.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/matrix_sdk/api.rb', line 44 def initialize(homeserver, **params) @homeserver = homeserver raise ArgumentError, 'Homeserver URL must be String or URI' unless @homeserver.is_a?(String) || @homeserver.is_a?(URI) @homeserver = URI.parse("#{'https://' unless @homeserver.start_with? 'http'}#{@homeserver}") unless @homeserver.is_a? URI @homeserver.path.gsub!(/\/?_matrix\/?/, '') if @homeserver.path =~ /_matrix\/?$/ raise ArgumentError, 'Please use the base URL for your HS (without /_matrix/)' if @homeserver.path.include? '/_matrix/' @protocols = params.fetch(:protocols, %i[CS]) @protocols = [@protocols] unless @protocols.is_a? Array @protocols << :CS if @protocols.include?(:AS) && !@protocols.include?(:CS) @proxy_uri = params.fetch(:proxy_uri, nil) @connection_address = params.fetch(:address, nil) @connection_port = params.fetch(:port, nil) @access_token = params.fetch(:access_token, nil) @device_id = params.fetch(:device_id, nil) @autoretry = params.fetch(:autoretry, true) @validate_certificate = params.fetch(:validate_certificate, false) @transaction_id = params.fetch(:transaction_id, 0) @backoff_time = params.fetch(:backoff_time, 5000) @read_timeout = params.fetch(:read_timeout, 240) @well_known = params.fetch(:well_known, {}) @global_headers = DEFAULT_HEADERS.dup @global_headers.merge!(params.fetch(:global_headers)) if params.key? :global_headers @http = nil login(user: @homeserver.user, password: @homeserver.password) if @homeserver.user && @homeserver.password && !@access_token && !params[:skip_login] && protocol?(:CS) @homeserver.userinfo = '' unless params[:skip_login] end |
Instance Attribute Details
#access_token ⇒ Object
Returns the value of attribute access_token.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def access_token @access_token end |
#autoretry ⇒ Object
Returns the value of attribute autoretry.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def autoretry @autoretry end |
#connection_address ⇒ Object
Returns the value of attribute connection_address.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def connection_address @connection_address end |
#connection_port ⇒ Object
Returns the value of attribute connection_port.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def connection_port @connection_port end |
#device_id ⇒ Object
Returns the value of attribute device_id.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def device_id @device_id end |
#global_headers ⇒ Object
Returns the value of attribute global_headers.
24 25 26 |
# File 'lib/matrix_sdk/api.rb', line 24 def global_headers @global_headers end |
#homeserver ⇒ Object
Returns the value of attribute homeserver.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def homeserver @homeserver end |
#protocols ⇒ Object (readonly)
Returns the value of attribute protocols.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def protocols @protocols end |
#proxy_uri ⇒ Object
Returns the value of attribute proxy_uri.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def proxy_uri @proxy_uri end |
#read_timeout ⇒ Object
Returns the value of attribute read_timeout.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def read_timeout @read_timeout end |
#validate_certificate ⇒ Object
Returns the value of attribute validate_certificate.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def validate_certificate @validate_certificate end |
#well_known ⇒ Object (readonly)
Returns the value of attribute well_known.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def well_known @well_known end |
Class Method Details
.new_for_domain(domain, target: :client, keep_wellknown: false, ssl: true, **params) ⇒ API
Create an API connection to a domain entry
This will follow the server discovery spec for client-server and federation
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/matrix_sdk/api.rb', line 91 def self.new_for_domain(domain, target: :client, keep_wellknown: false, ssl: true, **params) domain, port = domain.split(':') uri = URI("http#{ssl ? 's' : ''}://#{domain}") well_known = nil target_uri = nil if !port.nil? && !port.empty? target_uri = URI("https://#{domain}:#{port}") elsif target == :server # Attempt SRV record discovery target_uri = begin require 'resolv' resolver = Resolv::DNS.new resolver.getresource("_matrix._tcp.#{domain}") rescue StandardError nil end if target_uri.nil? well_known = begin data = Net::HTTP.get("https://#{domain}/.well-known/matrix/server") JSON.parse(data) rescue StandardError nil end target_uri = well_known['m.server'] if well_known&.key?('m.server') else target_uri = URI("https://#{target_uri.target}:#{target_uri.port}") end elsif %i[client identity].include? target # Attempt .well-known discovery well_known = begin data = Net::HTTP.get("https://#{domain}/.well-known/matrix/client") JSON.parse(data) rescue StandardError nil end if well_known key = 'm.homeserver' key = 'm.identity_server' if target == :identity if well_known.key?(key) && well_known[key].key?('base_url') uri = URI(well_known[key]['base_url']) target_uri = uri end end end # Fall back to direct domain connection target_uri ||= URI("https://#{domain}:8448") params[:well_known] = well_known if keep_wellknown new(uri, params.merge( address: target_uri.host, port: target_uri.port )) end |
Instance Method Details
#protocol?(protocol) ⇒ Boolean
153 154 155 |
# File 'lib/matrix_sdk/api.rb', line 153 def protocol?(protocol) protocols.include? protocol end |
#request(method, api, path, **options) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/matrix_sdk/api.rb', line 194 def request(method, api, path, **) url = homeserver.dup.tap do |u| u.path = api_to_path(api) + path u.query = [u.query, URI.encode_www_form(.fetch(:query))].flatten.compact.join('&') if [:query] u.query = nil if u.query.nil? || u.query.empty? end request = Net::HTTP.const_get(method.to_s.capitalize.to_sym).new url.request_uri request.body = [:body] if .key? :body request.body = request.body.to_json if .key?(:body) && !request.body.is_a?(String) request.body_stream = [:body_stream] if .key? :body_stream global_headers.each { |h, v| request[h] = v } if request.body || request.body_stream request.content_type = 'application/json' request.content_length = (request.body || request.body_stream).size end request['authorization'] = "Bearer #{access_token}" if access_token if .key? :headers [:headers].each do |h, v| request[h.to_s.downcase] = v end end failures = 0 loop do raise MatrixConnectionError, "Server still too busy to handle request after #{failures} attempts, try again later" if failures >= 10 print_http(request) begin response = http.request request rescue EOFError => e logger.error 'Socket closed unexpectedly' raise e end print_http(response) data = JSON.parse(response.body, symbolize_names: true) rescue nil if response.is_a? Net::HTTPTooManyRequests raise MatrixRequestError.new_by_code(data, response.code) unless autoretry failures += 1 waittime = data[:retry_after_ms] || data[:error][:retry_after_ms] || @backoff_time sleep(waittime.to_f / 1000.0) next end return MatrixSdk::Response.new self, data if response.is_a? Net::HTTPSuccess raise MatrixRequestError.new_by_code(data, response.code) if data raise MatrixConnectionError.class_by_code(response.code), response end end |