motion/http.rb in bubble-wrap-1.1.5 vs motion/http.rb in bubble-wrap-1.2.0.pre

- old
+ new

@@ -32,10 +32,11 @@ class Response attr_reader :body attr_reader :headers attr_accessor :status_code, :status_description, :error_message attr_reader :url + attr_reader :original_url def initialize(values={}) self.update(values) end @@ -84,10 +85,11 @@ # :payload<String> - data to pass to a POST, PUT, DELETE query. # :delegator - Proc, class or object to call when the file is downloaded. # a proc will receive a Response object while the passed object # will receive the handle_query_response method # :headers<Hash> - headers send with the request + # :cookies<Boolean> - Set whether cookies should be sent with request or not (Default: true) # Anything else will be available via the options attribute reader. # def initialize(url_string, http_method = :get, options={}) @method = http_method.upcase.to_s @delegator = options.delete(:action) || self @@ -99,21 +101,24 @@ @timeout = options.delete(:timeout) || 30.0 @headers = escape_line_feeds(options.delete :headers) @format = options.delete(:format) @cache_policy = options.delete(:cache_policy) || NSURLRequestUseProtocolCachePolicy @credential_persistence = options.delete(:credential_persistence) || NSURLCredentialPersistenceForSession + @cookies = options.key?(:cookies) ? options.delete(:cookies) : true @options = options @response = HTTP::Response.new + @follow_urls = options[:follow_urls] || true @url = create_url(url_string) @body = create_request_body @request = create_request + @original_url = @url.copy @connection = create_connection(request, self) @connection.start - UIApplication.sharedApplication.networkActivityIndicatorVisible = true + UIApplication.sharedApplication.networkActivityIndicatorVisible = true if defined?(UIApplication) end def to_s "#<#{self.class}:#{self.object_id} - Method: #{@method}, url: #{@url.description}, body: #{@body.description}, Payload: #{@payload}, Headers: #{@headers} Credentials: #{@credentials}, Timeout: #{@timeout}, \ Cache policy: #{@cache_policy}, response: #{@response.inspect} >" @@ -135,27 +140,32 @@ download_progress.call(@received_data.length.to_f, response_size) end end def connection(connection, willSendRequest:request, redirectResponse:redirect_response) + # abort early if the user has explicitly disabled redirects + if @options[:no_redirect] and redirect_response then + return nil + end @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 + @url = request.URL if @follow_urls request end end def connection(connection, didFailWithError: error) - log "HTTP Connection failed #{error.localizedDescription}" - UIApplication.sharedApplication.networkActivityIndicatorVisible = false + log "HTTP Connection to #{@url.absoluteString} failed #{error.localizedDescription}" + UIApplication.sharedApplication.networkActivityIndicatorVisible = false if defined?(UIApplication) @request.done_loading! @response.error_message = error.localizedDescription call_delegator_with_response end @@ -164,14 +174,14 @@ upload_progress.call(sending, written, expected) end end def connectionDidFinishLoading(connection) - UIApplication.sharedApplication.networkActivityIndicatorVisible = false + UIApplication.sharedApplication.networkActivityIndicatorVisible = false if defined?(UIApplication) @request.done_loading! response_body = NSData.dataWithData(@received_data) if @received_data - @response.update(status_code: status_code, body: response_body, headers: response_headers, url: @url) + @response.update(status_code: status_code, body: response_body, headers: response_headers, url: @url, original_url: @original_url) call_delegator_with_response end def connection(connection, didReceiveAuthenticationChallenge:challenge) @@ -201,10 +211,11 @@ timeoutInterval:@timeout) request.setHTTPMethod(@method) set_content_type request.setAllHTTPHeaderFields(@headers) request.setHTTPBody(@body) + request.setHTTPShouldHandleCookies(@cookies) patch_nsurl_request(request) request end @@ -258,30 +269,38 @@ end def append_form_params(body) 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) + body.appendData(s.dataUsingEncoding NSUTF8StringEncoding) end @payload_or_files_were_appended = true body end + def parse_file(key, value) + if value.is_a?(Hash) + raise InvalidFileError if value[:data].nil? + {data: value[:data], filename: value[:filename] || key} + else + {data: value, filename: key} + end + end + def append_files(body) @files.each do |key, value| - file_data = NSMutableData.new + file = parse_file(key, value) s = "--#{@boundary}\r\n" - s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{key}\"\r\n" + s += "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file[:filename]}\"\r\n" s += "Content-Type: application/octet-stream\r\n\r\n" + file_data = NSMutableData.new file_data.appendData(s.dataUsingEncoding NSUTF8StringEncoding) - file_data.appendData(value) + file_data.appendData(file[:data]) file_data.appendData("\r\n".dataUsingEncoding NSUTF8StringEncoding) body.appendData(file_data) end @payload_or_files_were_appended = true body @@ -309,11 +328,11 @@ end end def escape(string) if string - CFURLCreateStringByAddingPercentEscapes nil, string.to_s, "[]", ";=&,", KCFStringEncodingUTF8 + CFURLCreateStringByAddingPercentEscapes nil, string.to_s, nil, "!*'();:@&=+$,/?%#[]", KCFStringEncodingUTF8 end end def convert_payload_to_url params_array = process_payload_hash(@payload) @@ -374,5 +393,6 @@ end end end class InvalidURLError < StandardError; end +class InvalidFileError < StandardError; end