rbrainz 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGES +13 -1
  2. data/LICENSE +1 -1
  3. data/README +2 -2
  4. data/Rakefile +2 -2
  5. data/TODO +9 -2
  6. data/doc/README.rdoc +5 -5
  7. data/examples/getartist.rb +3 -2
  8. data/examples/getlabel.rb +3 -2
  9. data/examples/getrelease.rb +5 -2
  10. data/examples/getreleasegroup.rb +53 -0
  11. data/examples/gettrack.rb +3 -2
  12. data/examples/getuser.rb +2 -1
  13. data/examples/rate.rb +44 -0
  14. data/examples/searchartists.rb +3 -2
  15. data/examples/searchcdstubs.rb +41 -0
  16. data/examples/searchlabels.rb +3 -2
  17. data/examples/searchreleasegroups.rb +36 -0
  18. data/examples/searchreleases.rb +6 -4
  19. data/examples/searchtracks.rb +3 -2
  20. data/examples/submit_isrcs.rb +52 -0
  21. data/examples/tag.rb +3 -2
  22. data/lib/rbrainz.rb +2 -1
  23. data/lib/rbrainz/core_ext.rb +2 -1
  24. data/lib/rbrainz/core_ext/mbid.rb +2 -1
  25. data/lib/rbrainz/core_ext/net_http_digest.rb +3 -2
  26. data/lib/rbrainz/core_ext/range.rb +3 -2
  27. data/lib/rbrainz/core_ext/range/equality.rb +2 -1
  28. data/lib/rbrainz/data/countrynames.rb +6 -3
  29. data/lib/rbrainz/data/languagenames.rb +3 -2
  30. data/lib/rbrainz/data/releasetypenames.rb +3 -2
  31. data/lib/rbrainz/data/scriptnames.rb +3 -2
  32. data/lib/rbrainz/model.rb +3 -2
  33. data/lib/rbrainz/model/alias.rb +3 -2
  34. data/lib/rbrainz/model/artist.rb +11 -3
  35. data/lib/rbrainz/model/collection.rb +3 -2
  36. data/lib/rbrainz/model/default_factory.rb +18 -6
  37. data/lib/rbrainz/model/disc.rb +3 -2
  38. data/lib/rbrainz/model/entity.rb +2 -102
  39. data/lib/rbrainz/model/incomplete_date.rb +3 -2
  40. data/lib/rbrainz/model/individual.rb +11 -2
  41. data/lib/rbrainz/model/isrc.rb +100 -0
  42. data/lib/rbrainz/model/label.rb +5 -2
  43. data/lib/rbrainz/model/mbid.rb +28 -9
  44. data/lib/rbrainz/model/rateable.rb +34 -0
  45. data/lib/rbrainz/model/rating.rb +56 -0
  46. data/lib/rbrainz/model/relateable.rb +118 -0
  47. data/lib/rbrainz/model/relation.rb +2 -1
  48. data/lib/rbrainz/model/release.rb +17 -3
  49. data/lib/rbrainz/model/release_event.rb +3 -2
  50. data/lib/rbrainz/model/release_group.rb +97 -0
  51. data/lib/rbrainz/model/scored_collection.rb +3 -2
  52. data/lib/rbrainz/model/tag.rb +5 -4
  53. data/lib/rbrainz/model/taggable.rb +27 -0
  54. data/lib/rbrainz/model/track.rb +15 -2
  55. data/lib/rbrainz/model/user.rb +3 -2
  56. data/lib/rbrainz/utils.rb +2 -1
  57. data/lib/rbrainz/utils/data.rb +3 -2
  58. data/lib/rbrainz/utils/helper.rb +8 -2
  59. data/lib/rbrainz/version.rb +3 -2
  60. data/lib/rbrainz/webservice.rb +12 -7
  61. data/lib/rbrainz/webservice/filter.rb +53 -4
  62. data/lib/rbrainz/webservice/includes.rb +72 -11
  63. data/lib/rbrainz/webservice/mbxml.rb +129 -67
  64. data/lib/rbrainz/webservice/query.rb +156 -16
  65. data/lib/rbrainz/webservice/webservice.rb +104 -116
  66. data/test/lib/mock_webservice.rb +9 -2
  67. data/test/lib/test_entity.rb +2 -97
  68. data/test/lib/test_factory.rb +9 -1
  69. data/test/lib/test_rateable.rb +31 -0
  70. data/test/lib/test_relateable.rb +103 -0
  71. data/test/lib/test_taggable.rb +36 -0
  72. data/test/lib/testing_helper.rb +17 -2
  73. data/test/test-data/invalid/artist/ratings_1.xml +6 -0
  74. data/test/test-data/invalid/artist/ratings_2.xml +6 -0
  75. data/test/test-data/valid/artist/Tchaikovsky-2.xml +6 -0
  76. data/test/test-data/valid/label/Atlantic_Records_3.xml +6 -0
  77. data/test/test-data/valid/release-group/The_Cure_1.xml +36 -0
  78. data/test/test-data/valid/release/Highway_61_Revisited_2.xml +6 -0
  79. data/test/test-data/valid/track/Silent_All_These_Years_4.xml +3 -0
  80. data/test/test-data/valid/track/Silent_All_These_Years_6.xml +8 -0
  81. data/test/test_alias.rb +2 -1
  82. data/test/test_artist.rb +24 -2
  83. data/test/test_artist_filter.rb +2 -1
  84. data/test/test_artist_includes.rb +13 -3
  85. data/test/test_collection.rb +3 -2
  86. data/test/test_default_factory.rb +8 -1
  87. data/test/test_disc.rb +2 -1
  88. data/test/test_incomplete_date.rb +2 -1
  89. data/test/test_isrc.rb +87 -0
  90. data/test/test_label.rb +8 -1
  91. data/test/test_label_filter.rb +2 -1
  92. data/test/test_label_includes.rb +10 -3
  93. data/test/test_mbid.rb +2 -1
  94. data/test/test_mbxml.rb +93 -2
  95. data/test/test_query.rb +68 -5
  96. data/test/test_range_equality.rb +2 -1
  97. data/test/test_rating.rb +46 -0
  98. data/test/test_relation.rb +2 -1
  99. data/test/test_release.rb +37 -2
  100. data/test/test_release_event.rb +2 -1
  101. data/test/test_release_filter.rb +15 -2
  102. data/test/test_release_group.rb +104 -0
  103. data/test/test_release_group_filter.rb +61 -0
  104. data/test/test_release_group_includes.rb +46 -0
  105. data/test/test_release_includes.rb +16 -3
  106. data/test/test_scored_collection.rb +3 -2
  107. data/test/test_tag.rb +2 -1
  108. data/test/test_track.rb +28 -1
  109. data/test/test_track_filter.rb +2 -1
  110. data/test/test_track_includes.rb +13 -3
  111. data/test/test_utils.rb +2 -1
  112. data/test/test_webservice.rb +11 -1
  113. metadata +38 -20
  114. data/debian/changelog +0 -11
  115. data/debian/compat +0 -1
  116. data/debian/control +0 -13
  117. data/debian/copyright +0 -25
  118. data/debian/rules +0 -48
@@ -1,4 +1,5 @@
1
- # $Id: query.rb 218 2008-09-02 07:45:33Z phw $
1
+ # -*- coding: utf-8 -*-
2
+ # $Id: query.rb 270 2009-05-24 22:15:29Z phw $
2
3
  #
3
4
  # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
5
  # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
@@ -179,7 +180,7 @@ module MusicBrainz
179
180
  # or a options hash as expected by ArtistIncludes.
180
181
  #
181
182
  # If no artist with that ID can be found, include contains invalid tags
182
- # or there's a server problem, and exception is raised.
183
+ # or there's a server problem, an exception is raised.
183
184
  #
184
185
  # Raises:: ConnectionError, RequestError, ResourceNotFoundError, ResponseError
185
186
  def get_artist_by_id(id, includes = nil)
@@ -187,10 +188,10 @@ module MusicBrainz
187
188
  return get_entity_by_id(Model::Artist.entity_type, id, includes)
188
189
  end
189
190
 
190
- # Returns artists matching given criteria.
191
+ # Returns artists matching the given criteria.
191
192
  #
192
193
  # The parameter _filter_ must be an instance of ArtistFilter
193
- # or a options hash as expected by ArtistFilter.
194
+ # or an option hash as expected by ArtistFilter.
194
195
  #
195
196
  # Raises:: ConnectionError, RequestError, ResponseError
196
197
  def get_artists(filter)
@@ -198,13 +199,38 @@ module MusicBrainz
198
199
  return get_entities(Model::Artist.entity_type, filter)
199
200
  end
200
201
 
201
- # Returns an release.
202
+ # Returns a release group.
203
+ #
204
+ # The parameter _includes_ must be an instance of ReleaseGroupIncludes
205
+ # or a options hash as expected by ReleaseGroupIncludes.
206
+ #
207
+ # If no release group with that ID can be found, include contains invalid
208
+ # tags or there's a server problem, an exception is raised.
209
+ #
210
+ # Raises:: ConnectionError, RequestError, ResourceNotFoundError, ResponseError
211
+ def get_release_group_by_id(id, includes = nil)
212
+ includes = ReleaseGroupIncludes.new(includes) unless includes.nil? || includes.is_a?(ReleaseGroupIncludes)
213
+ return get_entity_by_id(Model::ReleaseGroup.entity_type, id, includes)
214
+ end
215
+
216
+ # Returns release groups matching the given criteria.
217
+ #
218
+ # The parameter _filter_ must be an instance of ReleaseGroupFilter
219
+ # or an option hash as expected by ReleaseGroupFilter.
220
+ #
221
+ # Raises:: ConnectionError, RequestError, ResponseError
222
+ def get_release_groups(filter)
223
+ filter = ReleaseGroupFilter.new(filter) unless filter.nil? || filter.is_a?(ReleaseGroupFilter)
224
+ return get_entities(Model::ReleaseGroup.entity_type, filter)
225
+ end
226
+
227
+ # Returns a release.
202
228
  #
203
229
  # The parameter _includes_ must be an instance of ReleaseIncludes
204
230
  # or a options hash as expected by ReleaseIncludes.
205
231
  #
206
232
  # If no release with that ID can be found, include contains invalid tags
207
- # or there's a server problem, and exception is raised.
233
+ # or there's a server problem, an exception is raised.
208
234
  #
209
235
  # Raises:: ConnectionError, RequestError, ResourceNotFoundError, ResponseError
210
236
  def get_release_by_id(id, includes = nil)
@@ -212,10 +238,10 @@ module MusicBrainz
212
238
  return get_entity_by_id(Model::Release.entity_type, id, includes)
213
239
  end
214
240
 
215
- # Returns releases matching given criteria.
241
+ # Returns releases matching the given criteria.
216
242
  #
217
243
  # The parameter _filter_ must be an instance of ReleaseFilter
218
- # or a options hash as expected by ReleaseFilter.
244
+ # or an option hash as expected by ReleaseFilter.
219
245
  #
220
246
  # Raises:: ConnectionError, RequestError, ResponseError
221
247
  def get_releases(filter)
@@ -223,13 +249,13 @@ module MusicBrainz
223
249
  return get_entities(Model::Release.entity_type, filter)
224
250
  end
225
251
 
226
- # Returns an track.
252
+ # Returns a track.
227
253
  #
228
254
  # The parameter _includes_ must be an instance of TrackIncludes
229
255
  # or a options hash as expected by TrackIncludes.
230
256
  #
231
257
  # If no track with that ID can be found, include contains invalid tags
232
- # or there's a server problem, and exception is raised.
258
+ # or there's a server problem, an exception is raised.
233
259
  #
234
260
  # Raises:: ConnectionError, RequestError, ResourceNotFoundError, ResponseError
235
261
  def get_track_by_id(id, includes = nil)
@@ -237,10 +263,10 @@ module MusicBrainz
237
263
  return get_entity_by_id(Model::Track.entity_type, id, includes)
238
264
  end
239
265
 
240
- # Returns tracks matching given criteria.
266
+ # Returns tracks matching the given criteria.
241
267
  #
242
268
  # The parameter _filter_ must be an instance of TrackFilter
243
- # or a options hash as expected by TrackFilter.
269
+ # or an option hash as expected by TrackFilter.
244
270
  #
245
271
  # Raises:: ConnectionError, RequestError, ResponseError
246
272
  def get_tracks(filter)
@@ -295,7 +321,7 @@ module MusicBrainz
295
321
  # Submit track to PUID mappings.
296
322
  #
297
323
  # The <em>tracks2puids</em> parameter has to be a Hash or Array
298
- # with track ID/PUID pairs. The track IDs are either instances of MBID,
324
+ # with track ID/PUID pairs. The track IDs are either instances of Model::MBID,
299
325
  # absolute URIs or the 36 character ASCII representation. PUIDs are
300
326
  # 36 characters ASCII strings.
301
327
  #
@@ -333,9 +359,59 @@ module MusicBrainz
333
359
  @webservice.post(:track, :params=>params)
334
360
  end
335
361
 
336
- # Submit tags for an entity. _mbid_ must be an instance of MBID identifying
362
+ # Submit track to ISRC mappings.
363
+ #
364
+ # The <em>tracks2isrcs</em> parameter has to be a Hash or Array
365
+ # with track ID/ISRC pairs. The track IDs are either instances of Model::MBID,
366
+ # absolute URIs or the 36 character ASCII representation. ISRCs are either
367
+ # instances of Model::ISRC or 12 character ASCII strings.
368
+ #
369
+ # Example:
370
+ # ws = Webservice::Webservice.new(
371
+ # :host => 'test.musicbrainz.org',
372
+ # :username => 'outsidecontext',
373
+ # :password => 'secret'
374
+ # )
375
+ #
376
+ # query = Webservice::Query.new(ws, :client_id=>'My Tagging App 1.0')
377
+ #
378
+ # query.submit_isrcs([
379
+ # ['7f574ec1-344c-4ae1-970d-3c757f9a717e', 'DED830049301'],
380
+ # ['1393122c-364c-4fb6-9a4b-17eddce90152', 'DED830049302'],
381
+ # ['2634965c-5299-4958-b0dc-47b166bb6898', 'DED830049303'],
382
+ # ['dad6b8a4-0412-4a80-9123-3e0ebddaf82d', 'DED830049304'],
383
+ # ['e1f7e805-33f3-4663-b294-3805b82405f9', 'DED830049305'],
384
+ # ['d9f932ad-de0d-44ca-bf35-ae8184f63909', 'DED830049306'],
385
+ # ['c983b62d-f528-433f-a402-a6317ce3d2d8', 'DED830049307'],
386
+ # ['9d50b06a-4136-427f-8d11-b2efb0141da6', 'DED830049308'],
387
+ # ['f2af3e3f-3f9f-4f8d-8b60-1d1b709aaf69', 'DED830049309'],
388
+ # ['059384bc-fb45-445e-ab77-950d6ccf587a', 'DED830049310'],
389
+ # ['2f4d7b47-a4ba-495a-b447-60b8287ed9c9', 'DED830049311'],
390
+ # ])
391
+ #
392
+ # Note that this method only works if a valid user name and
393
+ # password have been set. If username and/or password are incorrect,
394
+ # an AuthenticationError is raised. See the example in Query on
395
+ # how to supply authentication data.
396
+ #
397
+ # See:: http://musicbrainz.org/doc/ISRC
398
+ # Raises:: ConnectionError, RequestError, AuthenticationError, InvalidISRCError
399
+ def submit_isrcs(tracks2isrcs)
400
+ raise RequestError, 'Please supply a client ID' unless @client_id
401
+ params = [['client', @client_id.to_s]] # Encoded as utf-8
402
+
403
+ tracks2isrcs.each do |track_id, isrc|
404
+ track_id = Model::MBID.parse(track_id, :track).uuid
405
+ isrc = Model::ISRC.parse(isrc)
406
+ params << ['isrc', track_id + ' ' + isrc.to_str ]
407
+ end
408
+
409
+ @webservice.post(:track, :params=>params)
410
+ end
411
+
412
+ # Submit tags for an entity. _mbid_ must be an instance of Model::MBID identifying
337
413
  # the entity the tag should applied to and _tags_ is either and array or
338
- # Collection of Tag objects or a string with comma separated tags.
414
+ # Collection of Model::Tag objects or a string with comma separated tags.
339
415
  #
340
416
  # Note that this method only works if a valid user name and password have
341
417
  # been set. The tags will be applied for the authenticated user. If
@@ -395,6 +471,70 @@ module MusicBrainz
395
471
  return get_entities(:tag, "entity=#{mbid.entity}&id=#{mbid.uuid}").to_collection
396
472
  end
397
473
 
474
+ # Submit the user's rating for an entity. _mbid_ must be an instance of
475
+ # Model::MBID identifying the entity which should be rated and _rating_ is
476
+ # either a Model::Rating object or an integer value between 0 and 5.
477
+ #
478
+ # Note that this method only works if a valid user name and password have
479
+ # been set. The tags will be applied for the authenticated user. If
480
+ # username and/or password are incorrect, an AuthenticationError is raised.
481
+ # See the example in Query on how to supply authentication data.
482
+ #
483
+ # Example:
484
+ # ws = Webservice::Webservice.new(
485
+ # :host => 'test.musicbrainz.org',
486
+ # :username => 'outsidecontext',
487
+ # :password => 'secret'
488
+ # )
489
+ #
490
+ # query = Webservice::Query.new(ws)
491
+ #
492
+ # mbid = Model::MBID.new('http://musicbrainz.org/artist/10bf95b6-30e3-44f1-817f-45762cdc0de0')
493
+ # query.submit_user_rating(mbid, 5)
494
+ #
495
+ # See:: Model::Rating
496
+ # Raises:: ConnectionError, RequestError, AuthenticationError
497
+ def submit_user_rating(mbid, rating)
498
+ mbid = Model::MBID.parse(mbid)
499
+ params = {:entity=>mbid.entity, :id=>mbid.uuid, :rating=>rating.to_i}
500
+ @webservice.post(:rating, :params=>params)
501
+ end
502
+
503
+ # Returns the Model::Rating a user has applied to the entity
504
+ # identified by _mbid_.
505
+ #
506
+ # Note that this method only works if a valid user name and password have
507
+ # been set. Only the tags the authenticated user applied to the entity will
508
+ # be returned. If username and/or password are incorrect, an
509
+ # AuthenticationError is raised. See the example in Query on how to supply
510
+ # authentication data.
511
+ #
512
+ # Example:
513
+ # ws = Webservice::Webservice.new(
514
+ # :host => 'test.musicbrainz.org',
515
+ # :username => 'outsidecontext',
516
+ # :password => 'secret'
517
+ # )
518
+ #
519
+ # query = Webservice::Query.new(ws)
520
+ #
521
+ # mbid = Model::MBID.new('http://musicbrainz.org/artist/10bf95b6-30e3-44f1-817f-45762cdc0de0')
522
+ # rating = query.get_user_rating(mbid)
523
+ #
524
+ # See:: Model::Rating
525
+ # Raises:: ConnectionError, RequestError, ResponseError, AuthenticationError
526
+ def get_user_rating(mbid)
527
+ mbid = Model::MBID.parse(mbid)
528
+ stream = @webservice.get(:rating, :filter => "entity=#{mbid.entity}&id=#{mbid.uuid}")
529
+ begin
530
+ rating = MBXML.new(stream, @factory).get_entity(:user_rating)
531
+ rescue MBXML::ParseError => e
532
+ raise ResponseError, e.to_s
533
+ end
534
+ rating = Model::Rating.new unless rating
535
+ return rating
536
+ end
537
+
398
538
  private # ----------------------------------------------------------------
399
539
 
400
540
  # Helper method which will return any entity by ID.
@@ -430,4 +570,4 @@ module MusicBrainz
430
570
  end
431
571
 
432
572
  end
433
- end
573
+ end
@@ -1,4 +1,4 @@
1
- # $Id: webservice.rb 209 2008-06-22 21:53:55Z phw $
1
+ # $Id: webservice.rb 277 2009-05-25 19:33:26Z phw $
2
2
  #
3
3
  # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
4
  # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
@@ -72,7 +72,7 @@ module MusicBrainz
72
72
  # [:username] The username to authenticate with.
73
73
  # [:password] The password to authenticate with.
74
74
  # [:user_agent] Value sent in the User-Agent HTTP header. Defaults to "rbrainz/#{RBRAINZ_VERSION}"
75
- # [:proxy] URL for the proxy server to connect through
75
+ # [:proxy] URI for the proxy server to connect through
76
76
  def initialize(options={ :host=>nil, :port=>nil, :path_prefix=>'/ws', :username=>nil, :password=>nil, :user_agent=>"rbrainz/#{RBRAINZ_VERSION}", :proxy=>nil })
77
77
  Utils.check_options options, :host, :port, :path_prefix, :username, :password, :user_agent, :proxy
78
78
  @host = options[:host] ? options[:host] : 'musicbrainz.org'
@@ -83,14 +83,7 @@ module MusicBrainz
83
83
  @user_agent = options[:user_agent] ? options[:user_agent] : "rbrainz/#{RBRAINZ_VERSION}"
84
84
  @open_timeout = nil
85
85
  @read_timeout = nil
86
- @proxy = {}
87
- unless options[:proxy].nil?
88
- uri = URI.parse( options[:proxy] )
89
- @proxy[:host], @proxy[:port] = uri.host, uri.port
90
- if uri.userinfo
91
- @proxy[:username], @proxy[:password] = uri.userinfo.split(/:/)
92
- end
93
- end
86
+ set_proxy_options(options)
94
87
  end
95
88
 
96
89
  # Query the Webservice with HTTP GET.
@@ -108,55 +101,9 @@ module MusicBrainz
108
101
  # See:: IWebservice#get
109
102
  def get(entity_type, options={ :id=>nil, :include=>nil, :filter=>nil, :version=>1 })
110
103
  Utils.check_options options, :id, :include, :filter, :version
111
- url = URI.parse(create_uri(entity_type, options))
112
- request = Net::HTTP::Get.new(url.request_uri)
113
- request['User-Agent'] = @user_agent
114
- connection = Net::HTTP.new(url.host, url.port, @proxy[:host], @proxy[:port])
115
-
116
- # Set timeouts
117
- connection.open_timeout = @open_timeout if @open_timeout
118
- connection.read_timeout = @read_timeout if @read_timeout
119
-
120
- # Make the request
121
- begin
122
- response = connection.start do |http|
123
- response = http.request(request)
124
- if response.is_a?(Net::HTTPProxyAuthenticationRequired) && @proxy[:username] && @proxy[:password]
125
- request = Net::HTTP::Post.new(url.request_uri)
126
- request['User-Agent'] = @user_agent
127
- request.proxy_select_auth(@proxy[:username], @proxy[:password], response)
128
- request.set_form_data(options[:params])
129
- response = http.request(request)
130
- end
131
-
132
- if response.is_a?(Net::HTTPUnauthorized) && @username && @password
133
- request = Net::HTTP::Get.new(url.request_uri)
134
- request['User-Agent'] = @user_agent
135
- request.select_auth @username, @password, response
136
- response = http.request(request)
137
- end
138
- response
139
- end
140
- rescue Timeout::Error, Errno::ETIMEDOUT
141
- raise ConnectionError.new('%s timed out' % url.to_s)
142
- rescue SocketError => e
143
- raise ConnectionError.new('%s (%s)' % [url.to_s, e.to_s])
144
- end
145
-
146
- # Handle response errors.
147
- if response.is_a? Net::HTTPBadRequest # 400
148
- raise RequestError.new(url.to_s)
149
- elsif response.is_a? Net::HTTPUnauthorized # 401
150
- raise AuthenticationError.new(url.to_s)
151
- elsif response.is_a? Net::HTTPNotFound # 404
152
- raise ResourceNotFoundError.new(url.to_s)
153
- elsif response.is_a? Net::HTTPForbidden
154
- raise AuthenticationError.new(url.to_s)
155
- elsif not response.is_a? Net::HTTPSuccess
156
- raise ConnectionError.new(response.class.name)
157
- end
158
-
159
- return ::StringIO.new(response.body)
104
+ uri = create_uri(entity_type, options)
105
+ response = open_connection_and_make_request(uri, :get)
106
+ return response
160
107
  end
161
108
 
162
109
  # Send data to the web service via HTTP-POST.
@@ -177,68 +124,35 @@ module MusicBrainz
177
124
  # See:: IWebservice#post
178
125
  def post(entity_type, options={ :id=>nil, :params=>[], :version=>1 })
179
126
  Utils.check_options options, :id, :params, :version
180
- url = URI.parse(create_uri(entity_type, options))
181
- request = Net::HTTP::Post.new(url.request_uri)
182
- request['User-Agent'] = @user_agent
183
- request.set_form_data(options[:params])
184
- connection = Net::HTTP.new(url.host, url.port, @proxy[:host], @proxy[:port])
185
-
186
- # Set timeouts
187
- connection.open_timeout = @open_timeout if @open_timeout
188
- connection.read_timeout = @read_timeout if @read_timeout
189
-
190
- # Make the request
191
- begin
192
- response = connection.start do |http|
193
- response = http.request(request)
194
-
195
- if response.is_a?(Net::HTTPProxyAuthenticationRequired) && @proxy[:username] && @proxy[:password]
196
- request = Net::HTTP::Post.new(url.request_uri)
197
- request['User-Agent'] = @user_agent
198
- request.proxy_select_auth(@proxy[:username], @proxy[:password], response)
199
- request.set_form_data(options[:params])
200
- response = http.request(request)
201
- end
202
- if response.is_a?(Net::HTTPUnauthorized) && @username && @password
203
- request = Net::HTTP::Post.new(url.request_uri)
204
- request['User-Agent'] = @user_agent
205
- request.select_auth( @username, @password, response)
206
- request.set_form_data(options[:params])
207
- response = http.request(request)
208
- end
209
- response
210
- end
211
- rescue Timeout::Error, Errno::ETIMEDOUT
212
- raise ConnectionError.new('%s timed out' % url.to_s)
213
- rescue SocketError => e
214
- raise ConnectionError.new('%s (%s)' % [url.to_s, e.to_s])
215
- end
216
-
217
- # Handle response errors.
218
- if response.is_a? Net::HTTPBadRequest # 400
219
- raise RequestError.new(url.to_s)
220
- elsif response.is_a? Net::HTTPUnauthorized # 401
221
- raise AuthenticationError.new(url.to_s)
222
- elsif response.is_a? Net::HTTPNotFound # 404
223
- raise ResourceNotFoundError.new(url.to_s)
224
- elsif response.is_a? Net::HTTPForbidden
225
- raise AuthenticationError.new(url.to_s)
226
- elsif not response.is_a? Net::HTTPSuccess
227
- raise ConnectionError.new(response.class.name)
228
- end
229
-
230
- return ::StringIO.new(response.body)
127
+ uri = create_uri(entity_type, options)
128
+ response = open_connection_and_make_request(uri, :post, options[:params])
129
+ return response
231
130
  end
232
131
 
233
132
  private # ----------------------------------------------------------------
234
133
 
134
+ def set_proxy_options(options)
135
+ @proxy = {}
136
+ unless options[:proxy].nil?
137
+ uri = URI.parse( options[:proxy] )
138
+ @proxy[:host], @proxy[:port] = uri.host, uri.port
139
+ if uri.userinfo
140
+ @proxy[:username], @proxy[:password] = uri.userinfo.split(/:/)
141
+ end
142
+ end
143
+ end
144
+
235
145
  # Builds a request URI for querying the webservice.
236
- def create_uri(entity_type, options = {:id=>nil, :include=>nil, :filter=>nil, :version=>1, :type=>nil})
146
+ def create_uri(entity_type, options = {:id=>nil, :include=>nil, :filter=>nil, :version=>1, :type=>'xml'})
237
147
  # Make sure the version is set
238
148
  options[:version] = 1 if options[:version].nil?
239
149
  options[:type] = 'xml' if options[:type].nil?
240
-
241
- # Build the URI
150
+ uri = build_uri_without_querystring(entity_type, options)
151
+ uri = append_querystring_to_uri(uri, options)
152
+ return URI.parse(uri)
153
+ end
154
+
155
+ def build_uri_without_querystring(entity_type, options)
242
156
  if options[:id]
243
157
  # Make sure the id is a MBID object
244
158
  id = options[:id]
@@ -252,14 +166,88 @@ module MusicBrainz
252
166
  uri = 'http://%s:%d%s/%d/%s/' %
253
167
  [@host, @port, @path_prefix, options[:version], entity_type]
254
168
  end
255
-
256
- # Append the querystring
169
+ return uri
170
+ end
171
+
172
+ def append_querystring_to_uri(uri, options)
257
173
  querystring = []
258
174
  querystring << 'type=' + CGI.escape(options[:type]) unless options[:type].nil?
259
175
  querystring << options[:include].to_s unless options[:include].nil?
260
176
  querystring << options[:filter].to_s unless options[:filter].nil?
261
177
  uri += '?' + querystring.join('&') unless querystring.empty?
262
- return uri
178
+ end
179
+
180
+ def open_connection_and_make_request(uri, request_type, form_data=nil)
181
+ connection = create_connection(uri)
182
+ response = make_request(connection, uri, request_type, form_data)
183
+ handle_response_errors(uri, response)
184
+ return ::StringIO.new(response.body)
185
+ end
186
+
187
+ def create_connection(uri)
188
+ connection = Net::HTTP.new(uri.host, uri.port, @proxy[:host], @proxy[:port])
189
+ set_connection_timeouts(connection)
190
+ return connection
191
+ end
192
+
193
+ def make_request(connection, uri, request_type, form_data=nil)
194
+ response = nil
195
+ begin
196
+ connection.start do |http|
197
+ request = create_request(uri, request_type, form_data)
198
+ response = http.request(request)
199
+ if response.is_a?(Net::HTTPProxyAuthenticationRequired) && @proxy[:username] && @proxy[:password]
200
+ request = create_request(uri, request_type, form_data)
201
+ request.proxy_select_auth(@proxy[:username], @proxy[:password], response)
202
+ response = http.request(request)
203
+ end
204
+
205
+ if response.is_a?(Net::HTTPUnauthorized) && @username && @password
206
+ request = create_request(uri, request_type, form_data)
207
+ request.select_auth @username, @password, response
208
+ response = http.request(request)
209
+ end
210
+ response
211
+ end
212
+ rescue Timeout::Error, Errno::ETIMEDOUT
213
+ raise ConnectionError.new('%s timed out' % uri.to_s)
214
+ rescue SocketError => e
215
+ raise ConnectionError.new('%s (%s)' % [uri.to_s, e.to_s])
216
+ rescue ::Exception => e
217
+ raise ConnectionError.new(e.to_s)
218
+ end
219
+ return response
220
+ end
221
+
222
+ def set_connection_timeouts(connection)
223
+ connection.open_timeout = @open_timeout if @open_timeout
224
+ connection.read_timeout = @read_timeout if @read_timeout
225
+ end
226
+
227
+ def create_request(uri, request_type, form_data=nil)
228
+ if request_type == :post
229
+ request = Net::HTTP::Post.new(uri.request_uri)
230
+ else
231
+ request = Net::HTTP::Get.new(uri.request_uri)
232
+ end
233
+ request['User-Agent'] = @user_agent
234
+ request.set_form_data(form_data) unless form_data.nil?
235
+ return request
236
+ end
237
+
238
+ # Handles response errors and raises appropriate exceptions
239
+ def handle_response_errors(uri, response)
240
+ if response.is_a? Net::HTTPBadRequest # 400
241
+ raise RequestError.new(uri.to_s)
242
+ elsif response.is_a? Net::HTTPUnauthorized # 401
243
+ raise AuthenticationError.new(uri.to_s)
244
+ elsif response.is_a? Net::HTTPNotFound # 404
245
+ raise ResourceNotFoundError.new(uri.to_s)
246
+ elsif response.is_a? Net::HTTPForbidden
247
+ raise AuthenticationError.new(uri.to_s)
248
+ elsif not response.is_a? Net::HTTPSuccess
249
+ raise ConnectionError.new(response.class.name)
250
+ end
263
251
  end
264
252
 
265
253
  end