lib/parliament/request/open_search_request.rb in parliament-opensearch-0.2.5 vs lib/parliament/request/open_search_request.rb in parliament-opensearch-0.2.6
- old
+ new
@@ -1,18 +1,21 @@
module Parliament
module Request
# API request object, allowing the user to build a request to an OpenSearch API and build a response.
#
# @since 0.1.0
+ # attr [Hash] templates the different types and template urls set from the OpenSearch API description document.
class OpenSearchRequest < Parliament::Request::BaseRequest
+ attr_reader :templates
+
OPEN_SEARCH_PARAMETERS = {
- count: 10,
- start_index: 1,
- start_page: 1,
- language: '*',
- output_encoding: 'UTF-8',
- input_encoding: 'UTF-8'
+ count: 10,
+ start_index: 1,
+ start_page: 1,
+ language: '*',
+ output_encoding: 'UTF-8',
+ input_encoding: 'UTF-8'
}.freeze
# Creates a new instance of Parliament::OpenSearch::Request.
#
# An interesting note for #initialize is that setting description_url on the class means you don't need to pass in a description_url.
@@ -24,39 +27,40 @@
# @param [Hash] headers the headers being sent in the request.
# @param [Parliament::OpenSearch::Builder] builder the builder required to create the response.
def initialize(description_url: nil, headers: nil, builder: nil)
@description_url = description_url
- raise Parliament::OpenSearch::DescriptionError.new(@description_url), 'No description URL passed to Parliament::OpenSearchRequest#new and, no Parliament::OpenSearchRequest#base_url value set. Without a description URL, we are unable to make any search requests.' if @description_url.nil? && self.class.base_url.nil?
+ raise Parliament::OpenSearch::DescriptionError.new(@description_url), 'No description URL passed to Parliament::OpenSearchRequest#new and, no Parliament::OpenSearchRequest#base_url value set. Without a description URL, we are unable to make any search requests.' if @description_url.nil? && self.class.templates.nil?
- @base_url = Parliament::Request::OpenSearchRequest.get_description(@description_url) || self.class.base_url
+ @templates = Parliament::Request::OpenSearchRequest.get_description(@description_url) || self.class.templates
@open_search_parameters = self.class.open_search_parameters
- super(base_url: @base_url, headers: headers, builder: builder)
+ super(base_url: nil, headers: headers, builder: builder)
end
# Sets up the query url using the base_url and parameters, then make an HTTP GET request and process results.
#
# @see Parliament::BaseRequest#get
# @params [Hash] search_params the search parameters to be passed to the OpenSearch API. This is the search term and/or any of the keys from OPEN_SEARCH_PARAMETERS, depending on the parameters allowed in the API.
+ # @params [String] type the type of data requested, eg. 'application/atom+xml'.
# @params [Hash] params any extra parameters.
- def get(search_params, params: nil)
- setup_query_url(search_params)
+ def get(search_params, type: nil, params: nil)
+ setup_query_url(search_params, type)
super(params: params)
end
private
- # @attr [String] base_url the base url for the OpenSearch API description. (expected: http://example.com - without the trailing slash).
+ # @attr [String] templates the different types and template urls set from the OpenSearch API description document.
# @attr [Hash] open_search_parameters the possible parameters to use in the query url.
class << self
- attr_reader :description_url, :base_url
+ attr_reader :description_url, :templates
def description_url=(description_url)
@description_url = description_url
- @base_url = Parliament::Request::OpenSearchRequest.get_description(@description_url)
+ @templates = Parliament::Request::OpenSearchRequest.get_description(@description_url)
end
def open_search_parameters
OPEN_SEARCH_PARAMETERS.dup
end
@@ -69,34 +73,47 @@
rescue URI::InvalidURIError => e
raise Parliament::OpenSearch::DescriptionError.new(url), "Invalid description URI passed '#{url}': #{e.message}"
end
request = Parliament::Request::BaseRequest.new(base_url: url,
- headers: { 'Accept' => 'application/opensearchdescription+xml',
- 'Ocp-Apim-Subscription-Key' => ENV['OPENSEARCH_AUTH_TOKEN']
+ headers: {
+ 'Accept' => 'application/opensearchdescription+xml',
+ 'Ocp-Apim-Subscription-Key' => ENV['OPENSEARCH_AUTH_TOKEN']
})
xml_response = request.get
begin
xml_root = REXML::Document.new(xml_response.response.body).root
- template = xml_root.elements['Url'].attributes['template']
+ templates = { url: [] }
+ xml_root.elements.each('Url') do |url|
+ type = url.attributes['type']
+ template = url.attributes['template']
+ templates[:url] << { type: type, template: template }
+ end
- raise Parliament::OpenSearch::DescriptionError.new(url), "The document found does not contain a require node. Attempted to get a 'Url' element with the attribute 'template'. Please check the description document at '#{url}' and try again." if template.nil?
+ raise Parliament::OpenSearch::DescriptionError.new(url), "The document found does not contain the required node. Attempted to get a 'Url' element with the attribute 'template'. Please check the description document at '#{url}' and try again." if templates[:url].empty?
rescue NoMethodError
raise Parliament::OpenSearch::DescriptionError.new(url), "The document found does not appear to be XML. Please check the description document at '#{url}' and try again."
end
- template
+ templates
end
end
def query_url
@query_url
end
- def setup_query_url(search_params)
+ def setup_query_url(search_params, type = nil)
search_terms = search_params[:query]
- query_url = @base_url.dup
+ type ||= 'application/atom+xml'
+
+ url_hash = @templates[:url].select { |url| url[:type] == type }.first
+
+ raise Parliament::OpenSearch::DescriptionError.new(type), "There is no url for the requested type '#{type}'." if url_hash.nil?
+
+ query_url = url_hash[:template].dup
+
query_url.gsub!('{searchTerms}', search_terms)
@open_search_parameters.each do |key, value|
camel_case_key = ActiveSupport::Inflector.camelize(key.to_s, false)
if search_params.keys.include?(key)