Class: MatrixSdk::Api
- Extended by:
- Extensions
- 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.
-
#open_timeout ⇒ Object
Returns the value of attribute open_timeout.
-
#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
Check if a protocol is enabled on the API connection.
-
#request(method, api, path, **options) ⇒ Object
Perform a raw Matrix API request.
Methods included from Extensions
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, #bind_3pid, #change_password, #claim_one_time_keys, #client_api_unstable_features, #client_api_versions, #complete_3pid_add, #create_filter, #create_room, #deactivate_account, #delete_3pid, #delete_device, #forget_room, #get_3pids, #get_account_data, #get_avatar_url, #get_device, #get_devices, #get_display_name, #get_download_url, #get_filter, #get_joined_rooms, #get_key_changes, #get_media_config, #get_membership, #get_notifications, #get_presence_status, #get_profile, #get_public_rooms, #get_pushers, #get_pushrule, #get_pushrule_actions, #get_pushrule_enabled, #get_pushrules, #get_room_account_data, #get_room_aliases, #get_room_avatar, #get_room_creation_info, #get_room_directory_visibility, #get_room_encryption_settings, #get_room_event, #get_room_guest_access, #get_room_history_visibility, #get_room_id, #get_room_join_rules, #get_room_joined_members, #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_state_all, #get_room_topic, #get_turn_server, #get_url_preview, #get_user_tags, #invite_user, #join_room, #join_room_id, #keys_query, #kick_user, #leave_room, #login, #logout, #logout_all, #media_upload, #redact_event, #register, #register_email_request, #register_msisdn_request, #remove_room_alias, #remove_user_tag, #report_event, #request_email_login_token, #request_msisdn_login_token, #send_content, #send_emote, #send_location, #send_message, #send_message_event, #send_notice, #send_state_event, #send_to_device, #set_account_data, #set_avatar_url, #set_device, #set_display_name, #set_membership, #set_presence_status, #set_pusher, #set_pushrule_actions, #set_pushrule_enabled, #set_room_account_data, #set_room_alias, #set_room_avatar, #set_room_directory_visibility, #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, #set_typing, #sync, #unban_user, #unbind_3pid, #username_available?, #whoami?, #whois
Methods included from Protocols::AS
Methods included from Logging
Constructor Details
#initialize(homeserver, **params) ⇒ Api
Returns a new instance of Api.
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 74 75 76 |
# File 'lib/matrix_sdk/api.rb', line 46 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) @open_timeout = params.fetch(:open_timeout, 60) @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.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def access_token @access_token end |
#autoretry ⇒ Object
Returns the value of attribute autoretry.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def autoretry @autoretry end |
#connection_address ⇒ Object
Returns the value of attribute connection_address.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def connection_address @connection_address end |
#connection_port ⇒ Object
Returns the value of attribute connection_port.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def connection_port @connection_port end |
#device_id ⇒ Object
Returns the value of attribute device_id.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def device_id @device_id end |
#global_headers ⇒ Object
Returns the value of attribute global_headers.
25 26 27 |
# File 'lib/matrix_sdk/api.rb', line 25 def global_headers @global_headers end |
#homeserver ⇒ Object
Returns the value of attribute homeserver.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def homeserver @homeserver end |
#open_timeout ⇒ Object
Returns the value of attribute open_timeout.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def open_timeout @open_timeout end |
#protocols ⇒ Object (readonly)
Returns the value of attribute protocols.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def protocols @protocols end |
#proxy_uri ⇒ Object
Returns the value of attribute proxy_uri.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def proxy_uri @proxy_uri end |
#read_timeout ⇒ Object
Returns the value of attribute read_timeout.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def read_timeout @read_timeout end |
#validate_certificate ⇒ Object
Returns the value of attribute validate_certificate.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 def validate_certificate @validate_certificate end |
#well_known ⇒ Object (readonly)
Returns the value of attribute well_known.
26 27 28 |
# File 'lib/matrix_sdk/api.rb', line 26 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
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 152 153 154 155 156 |
# File 'lib/matrix_sdk/api.rb', line 94 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? # If the domain is fully qualified according to Matrix (FQDN and port) then skip discovery 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? # Attempt .well-known discovery for server-to-server 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
Check if a protocol is enabled on the API connection
166 167 168 |
# File 'lib/matrix_sdk/api.rb', line 166 def protocol?(protocol) protocols.include? protocol end |
#request(method, api, path, **options) ⇒ Object
Perform a raw Matrix API request
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/matrix_sdk/api.rb', line 236 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 |