Skip to content

Commit 6b7cbcc

Browse files
committed
Call setConfigXML via POST and change encoding method
Now it uses an encoding method that is more similar to the one used in BigBlueButton. Fixes issues when there was an asterisk (*) in the config.xml. Also made setConfigXML be sent always via POST, so that the XML will be in the body of the request and not in the URL. It was generating URLs way too long since the default config.xml is growing.
1 parent 41fbc58 commit 6b7cbcc

2 files changed

Lines changed: 51 additions & 24 deletions

File tree

lib/bigbluebutton_api.rb

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ def is_meeting_running?(meeting_id, options={})
226226
# in this hash and they will be added to the API call.
227227
def join_meeting_url(meeting_id, user_name, password, options={})
228228
params = { :meetingID => meeting_id, :password => password, :fullName => user_name }.merge(options)
229-
get_url(:join, params)
229+
url, data = get_url(:join, params)
230+
url
230231
end
231232

232233
# Returns a hash object containing the information of a meeting.
@@ -600,7 +601,8 @@ def test_connection
600601
end
601602

602603
def check_url
603-
get_url(:check)
604+
url, data = get_url(:check)
605+
url
604606
end
605607

606608
# API's are equal if all the following attributes are equal.
@@ -627,31 +629,35 @@ def last_xml_response
627629
# params (Hash):: The parameters to be passed in the URL
628630
def get_url(method, params={})
629631
if method == :index
630-
return @url
632+
return @url, nil
631633
elsif method == :check
632634
baseurl = URI.join(@url, "/").to_s
633-
return "#{baseurl}check"
635+
return "#{baseurl}check", nil
634636
end
635637

636-
url = "#{@url}/#{method}?"
637-
638638
# stringify and escape all params
639639
params.delete_if { |k, v| v.nil? } unless params.nil?
640640
# some API calls require the params to be sorted
641641
# first make all keys symbols, so the comparison works
642642
params = params.inject({}){ |memo,(k,v)| memo[k.to_sym] = v; memo }
643643
params = Hash[params.sort]
644644
params_string = ""
645-
params_string = params.map{ |k,v| "#{k}=" + CGI::escape(v.to_s) unless k.nil? || v.nil? }.join("&")
645+
params_string = params.map{ |k,v| "#{k}=" + URI.encode_www_form_component(v.to_s) unless k.nil? || v.nil? }.join("&")
646646

647647
# checksum calc
648648
checksum_param = params_string + @secret
649649
checksum_param = method.to_s + checksum_param
650650
checksum = Digest::SHA1.hexdigest(checksum_param)
651651

652-
# final url
653-
url += "#{params_string}&" unless params_string.empty?
654-
url += "checksum=#{checksum}"
652+
if method == :setConfigXML
653+
params_string = "checksum=#{checksum}&#{params_string}"
654+
return "#{@url}/#{method}", params_string
655+
else
656+
url = "#{@url}/#{method}?"
657+
url += "#{params_string}&" unless params_string.empty?
658+
url += "checksum=#{checksum}"
659+
return url, nil
660+
end
655661
end
656662

657663
# Performs an API call.
@@ -668,7 +674,9 @@ def get_url(method, params={})
668674
# raw (boolean):: If true, returns the data as it was received. Will not parse it into a Hash,
669675
# check for errors or throw exceptions.
670676
def send_api_request(method, params={}, data=nil, raw=false)
671-
url = get_url(method, params)
677+
# if the method returns a body, use it as the data in the post request
678+
url, body = get_url(method, params)
679+
data = body if body
672680

673681
@http_response = send_request(url, data)
674682
return {} if @http_response.body.empty?
@@ -718,7 +726,7 @@ def send_request(url, data=nil)
718726
response = http.get(url_parsed.request_uri, @request_headers)
719727
else
720728
puts "BigBlueButtonAPI: Sending as a POST request with data.size = #{data.size}" if @debug
721-
opts = { 'Content-Type' => 'text/xml' }.merge @request_headers
729+
opts = { 'Content-Type' => 'application/x-www-form-urlencoded' }.merge @request_headers
722730
response = http.post(url_parsed.request_uri, data, opts)
723731
end
724732
puts "BigBlueButtonAPI: URL response = #{response.body}" if @debug

spec/bigbluebutton_api_spec.rb

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@
226226
:userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
227227
}
228228

229-
before { api.should_receive(:get_url).with(:join, params).and_return("test-url") }
229+
before { api.should_receive(:get_url).with(:join, params).and_return(["test-url", nil]) }
230230
it {
231231
options = { :userID => "id123", :webVoiceConf => 12345678, :createTime => 9876543 }
232232
api.join_meeting_url("meeting-id", "Name", "pw", options).should == "test-url"
@@ -409,21 +409,21 @@
409409
describe "#get_url" do
410410

411411
context "when method = :index" do
412-
it { api.get_url(:index).should == api.url }
412+
it { api.get_url(:index).should == [api.url, nil] }
413413
end
414414

415415
context "when method = :check" do
416416
it {
417417
api.url = 'http://my-test-server.com/bigbluebutton/api'
418-
api.get_url(:check).should == 'http://my-test-server.com/check'
418+
api.get_url(:check).should == ['http://my-test-server.com/check', nil]
419419
}
420420
end
421421

422422
context "when method != :index" do
423423
context "validates the entire url" do
424424
context "with params" do
425425
let(:params) { { :param1 => "value1", :param2 => "value2" } }
426-
subject { api.get_url(:join, params) }
426+
subject { api.get_url(:join, params)[0] }
427427
it {
428428
# the hash can be sorted differently depending on the ruby version
429429
if params.map{ |k,v| "#{k}" }.join =~ /^param1/
@@ -435,35 +435,54 @@
435435
end
436436

437437
context "without params" do
438-
subject { api.get_url(:join) }
438+
subject { api.get_url(:join)[0] }
439439
it { subject.should match(/#{url}\/join\?[^&]/) }
440440
end
441441
end
442442

443+
context "when method = :setConfigXML" do
444+
it {
445+
api.url = 'http://my-test-server.com/bigbluebutton/api'
446+
response = api.get_url(:setConfigXML, { param1: 1, param2: 2 })
447+
response[0].should eql('http://my-test-server.com/bigbluebutton/api/setConfigXML')
448+
response[1].should match(/checksum=.*&param1=1&param2=2/)
449+
}
450+
end
451+
443452
context "discards params with nil value" do
444453
let(:params) { { :param1 => "value1", :param2 => nil } }
445-
subject { api.get_url(:join, params) }
454+
subject { api.get_url(:join, params)[0] }
446455
it { subject.should_not match(/param2=/) }
447456
end
448457

449458
context "escapes all params" do
450459
let(:params) { { :param1 => "value with spaces", :param2 => "@$" } }
451-
subject { api.get_url(:join, params) }
460+
subject { api.get_url(:join, params)[0] }
452461
it { subject.should match(/param1=value\+with\+spaces/) }
453462
it { subject.should match(/param2=%40%24/) }
454463
end
455464

465+
[ [' ', '+'],
466+
['*', '*']
467+
].each do |values|
468+
context "escapes #{values[0].inspect} as #{values[1].inspect}" do
469+
let(:params) { { param1: "before#{values[0]}after" } }
470+
subject { api.get_url(:join, params)[0] }
471+
it { subject.should match(/param1=before#{Regexp.quote(values[1])}after/) }
472+
end
473+
end
474+
456475
context "includes the checksum" do
457476
let(:params) { { :param1 => "value1", :param2 => "value2" } }
458477
let(:checksum) {
459478
# the hash can be sorted differently depending on the ruby version
460-
if params.map{ |k,v| "#{k}" }.join =~ /^param1/
479+
if params.map{ |k,v| k }.join =~ /^param1/
461480
"67882ae54f49600f56f358c10d24697ef7d8c6b2"
462481
else
463482
"85a54e28e4ec18bfdcb214a73f74d35b09a84176"
464483
end
465484
}
466-
subject { api.get_url(:join, params) }
485+
subject { api.get_url(:join, params)[0] }
467486
it { subject.should match(/checksum=#{checksum}$/) }
468487
end
469488
end
@@ -477,7 +496,7 @@
477496
let(:make_request) { api.send_api_request(method, params, data) }
478497
let(:response_mock) { mock() } # mock of what send_request() would return
479498

480-
before { api.should_receive(:get_url).with(method, params).and_return(url) }
499+
before { api.should_receive(:get_url).with(method, params).and_return([url, nil]) }
481500

482501
context "returns an empty hash if the response body is empty" do
483502
before do
@@ -567,7 +586,7 @@
567586
let(:data) { "any data" }
568587
before {
569588
path = "/res?param1=value1&checksum=12345"
570-
opts = { 'Content-Type' => 'text/xml' }
589+
opts = { 'Content-Type' => 'application/x-www-form-urlencoded' }
571590
@http_mock.should_receive(:post).with(path, data, opts).and_return("ok")
572591
}
573592
it {
@@ -589,7 +608,7 @@
589608
let(:data) { "any data" }
590609
before {
591610
path = "/res?param1=value1&checksum=12345"
592-
opts = { 'Content-Type' => 'text/xml', :anything => "anything" }
611+
opts = { 'Content-Type' => 'application/x-www-form-urlencoded', :anything => "anything" }
593612
@http_mock.should_receive(:post).with(path, data, opts).and_return("ok")
594613
}
595614
it {

0 commit comments

Comments
 (0)