motion/http.rb in bubble-wrap-1.1.2 vs motion/http.rb in bubble-wrap-1.1.3
- old
+ new
@@ -17,44 +17,43 @@
# BubbleWrap::HTTP.get("https://api.github.com/users/mattetti", {credentials: {username: 'matt', password: 'aimonetti'}}) do |response|
# p response.body.to_str # prints the response's body
# end
#
def self.get(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :get, options)
+ create_query(url, :get, options, block)
end
# Make a POST request
def self.post(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :post, options)
+ create_query(url, :post, options, block)
end
# Make a PUT request
def self.put(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :put, options)
+ create_query(url, :put, options, block)
end
# Make a DELETE request
def self.delete(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :delete, options)
+ create_query(url, :delete, options, block)
end
# Make a HEAD request
def self.head(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :head, options)
+ create_query(url, :head, options, block)
end
# Make a PATCH request
def self.patch(url, options={}, &block)
- options[:action] = block if block_given?
- HTTP::Query.new(url, :patch, options)
+ create_query(url, :patch, options, block)
end
+ def self.create_query(url, method, options, block)
+ options[:action] = block if block
+ HTTP::Query.new(url, method, options)
+ end
+
# Response class wrapping the results of a Query's response
class Response
attr_reader :body
attr_reader :headers
attr_accessor :status_code, :error_message
@@ -93,11 +92,11 @@
attr_reader :response
attr_reader :status_code
attr_reader :response_headers
attr_reader :response_size
attr_reader :options
-
+ CLRF = "\r\n"
# ==== Parameters
# url<String>:: url of the resource to download
# http_method<Symbol>:: Value representing the HTTP method to use
# options<Hash>:: optional options used for the query
#
@@ -125,11 +124,11 @@
@response = HTTP::Response.new
@url = create_url(url_string)
@body = create_request_body
@request = create_request
- set_content_type
+
@connection = create_connection(request, self)
@connection.start
UIApplication.sharedApplication.networkActivityIndicatorVisible = true
end
@@ -155,19 +154,22 @@
download_progress.call(@received_data.length.to_f, response_size)
end
end
def connection(connection, willSendRequest:request, redirectResponse:redirect_response)
- @redirection ||= 0
- @redirection += 1
- log "##{@redirection} HTTP redirection: #{request} - #{self.description}"
- new_request = request.mutableCopy
- # new_request.setValue(@credentials.inspect, forHTTPHeaderField:'Authorization') # disabled while we figure this one out
- new_request.setAllHTTPHeaderFields(@headers) if @headers
- @connection.cancel
- @connection = create_connection(new_request, self)
- new_request
+ @redirect_count ||= 0
+ @redirect_count += 1
+ log "##{@redirect_count} HTTP redirect_count: #{request.inspect} - #{self.description}"
+
+ if @redirect_count >= 30
+ @response.error_message = "Too many redirections"
+ @request.done_loading!
+ call_delegator_with_response
+ nil
+ else
+ request
+ end
end
def connection(connection, didFailWithError: error)
log "HTTP Connection failed #{error.localizedDescription}"
UIApplication.sharedApplication.networkActivityIndicatorVisible = false
@@ -210,106 +212,118 @@
request = NSMutableURLRequest.requestWithURL(@url,
cachePolicy:@cache_policy,
timeoutInterval:@timeout)
request.setHTTPMethod(@method)
+ set_content_type
request.setAllHTTPHeaderFields(@headers)
request.setHTTPBody(@body)
patch_nsurl_request(request)
request
end
+ def set_content_type
+ return if headers_provided?
+ return if (@method == "GET" || @method == "HEAD")
+ @headers ||= {}
+ @headers["Content-Type"] = case @format
+ when :json
+ "application/json"
+ when :xml
+ "application/xml"
+ when :text
+ "text/plain"
+ else
+ if @format == :form_data || @payload_or_files_were_appended
+ "multipart/form-data; boundary=#{@boundary}"
+ else
+ "application/x-www-form-urlencoded"
+ end
+ end
+ end
+
+ def headers_provided?
+ @headers && @headers.keys.find {|k| k.downcase == 'content-type'}
+ end
+
def create_request_body
return nil if (@method == "GET" || @method == "HEAD")
return nil unless (@payload || @files)
body = NSMutableData.data
append_payload(body) if @payload
append_files(body) if @files
- append_body_boundary(body) if @set_body_to_close_boundary
+ append_body_boundary(body) if @payload_or_files_were_appended
log "Built HTTP body: \n #{body.to_str}"
body
end
- def set_content_type
- # if no headers provided, set content-type automatically
- if @headers.nil? || !@headers.keys.find {|k| k.downcase == 'content-type'}
- @headers ||= {}
- @headers["Content-Type"] = case @format
- when :json
- "application/json"
- when :xml
- "application/xml"
- when :text
- "text/plain"
- else
- if @format == :form_data || @set_body_to_close_boundary
- "multipart/form-data; boundary=#{@boundary}"
- else
- "application/x-www-form-urlencoded"
- end
- end
- end
- end
-
def append_payload(body)
if @payload.is_a?(NSData)
body.appendData(@payload)
+ elsif @payload.is_a?(String)
+ body.appendData(@payload.dataUsingEncoding NSUTF8StringEncoding)
else
append_form_params(body)
end
body
end
def append_form_params(body)
- # puts "*** append_form #{@payload}"
- if @payload.is_a?(String)
- body.appendData(@payload.dataUsingEncoding NSUTF8StringEncoding)
- else
- list = process_payload_hash(@payload)
- list.each do |key, value|
- form_data = NSMutableData.new
- s = "\r\n--#{@boundary}\r\n"
- s += "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
- s += value.to_s
- form_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
- body.appendData(form_data)
- end
- @set_body_to_close_boundary = true
+ list = process_payload_hash(@payload)
+ list.each do |key, value|
+ form_data = NSMutableData.new
+ s = "--#{@boundary}\r\n"
+ s += "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n"
+ s += value.to_s
+ s += "\r\n"
+ form_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
+ body.appendData(form_data)
end
+ @payload_or_files_were_appended = true
body
end
def append_files(body)
@files.each do |key, value|
file_data = NSMutableData.new
- s = "\r\n--#{@boundary}\r\n"
+ s = "--#{@boundary}\r\n"
s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{key}\"\r\n"
s += "Content-Type: application/octet-stream\r\n\r\n"
file_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding)
file_data.appendData(value)
+ file_data.appendData("\r\n".dataUsingEncoding NSUTF8StringEncoding)
body.appendData(file_data)
end
- @set_body_to_close_boundary = true
+ @payload_or_files_were_appended = true
body
end
def append_body_boundary(body)
- body.appendData("\r\n--#{@boundary}--\r\n".dataUsingEncoding NSUTF8StringEncoding)
+ body.appendData("--#{@boundary}--\r\n".dataUsingEncoding NSUTF8StringEncoding)
end
def create_url(url_string)
if (@method == "GET" || @method == "HEAD") && @payload
convert_payload_to_url if @payload.is_a?(Hash)
url_string += "?#{@payload}"
end
- NSURL.URLWithString(url_string.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding)
+ url = NSURL.URLWithString(url_string.stringByAddingPercentEscapesUsingEncoding NSUTF8StringEncoding)
+
+ validate_url(url)
+ url
end
+ def validate_url(url)
+ if !NSURLConnection.canHandleRequest(NSURLRequest.requestWithURL(url))
+ raise InvalidURLError, "Invalid URL provided (Make sure you include a valid URL scheme, e.g. http:// or similar)."
+ end
+ end
+
def convert_payload_to_url
params_array = process_payload_hash(@payload)
params_array.map! { |key, value| "#{key}=#{value}" }
@payload = params_array.join("&")
end
@@ -340,18 +354,18 @@
def escape_line_feeds(hash)
return nil if hash.nil?
escaped_hash = {}
- hash.each{|k,v| escaped_hash[k] = v.gsub("\n", '\\n') }
+ hash.each{|k,v| escaped_hash[k] = v.gsub("\n", CLRF) }
escaped_hash
end
def patch_nsurl_request(request)
request.instance_variable_set("@done_loading", false)
- def request.done_loading; @done_loading; end
+ def request.done_loading?; @done_loading; end
def request.done_loading!; @done_loading = true; end
end
def call_delegator_with_response
if @delegator.respond_to?(:call)
@@ -365,5 +379,7 @@
end
end
end
end
+
+class InvalidURLError < StandardError; end