~ubuntu-branches/ubuntu/saucy/ruby-excon/saucy-proposed

« back to all changes in this revision

Viewing changes to lib/excon/connection.rb

  • Committer: Package Import Robot
  • Author(s): Laurent Bigonville
  • Date: 2012-04-17 17:46:25 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120417174625-lw1k4ybpynvvrqsd
Tags: 0.13.4-1
* New upstream release
* debian/patches/01_use_ca-certificate.patch: Use SSL certificates from
  ca-certificate package
* debian/control: Recommends ca-certificates package

Show diffs side-by-side

added added

removed removed

Lines of Context:
79
79
        params[:path].insert(0, '/')
80
80
      end
81
81
 
 
82
      if block_given?
 
83
        puts("Excon requests with a block are deprecated, pass :response_block instead (#{caller.first})")
 
84
        params[:response_block] = Proc.new
 
85
      end
 
86
 
82
87
      if params.has_key?(:instrumentor)
83
88
        if (retries_remaining ||= params[:retry_limit]) < params[:retry_limit]
84
89
          event_name = "#{params[:instrumentor_name]}.retry"
86
91
          event_name = "#{params[:instrumentor_name]}.request"
87
92
        end
88
93
        params[:instrumentor].instrument(event_name, params) do
89
 
          request_kernel(params, &block)
 
94
          request_kernel(params)
90
95
        end
91
96
      else
92
 
        request_kernel(params, &block)
 
97
        request_kernel(params)
93
98
      end
94
99
    rescue => request_error
95
100
      if params[:idempotent] && [Excon::Errors::SocketError,
140
145
 
141
146
  private
142
147
 
143
 
    def request_kernel(params, &block)
 
148
    def detect_content_length(body)
 
149
      if body.is_a?(String)
 
150
        if FORCE_ENC
 
151
          body.force_encoding('BINARY')
 
152
        end
 
153
        body.length
 
154
      elsif body.respond_to?(:size)
 
155
        # IO object: File, Tempfile, etc.
 
156
        body.size
 
157
      else
 
158
        begin
 
159
          File.size(body) # for 1.8.7 where file does not have size
 
160
        rescue
 
161
          0
 
162
        end
 
163
      end
 
164
    end
 
165
 
 
166
    def request_kernel(params)
144
167
      begin
145
168
        response = if params[:mock]
146
 
          invoke_stub(params, &block)
 
169
          invoke_stub(params)
147
170
        else
148
171
          socket.params = params
149
172
          # start with "METHOD /path"
174
197
          # finish first line with "HTTP/1.1\r\n"
175
198
          request << HTTP_1_1
176
199
 
177
 
          # calculate content length and set to handle non-ascii
178
 
          unless params[:headers].has_key?('Content-Length')
 
200
          if params.has_key?(:request_block)
 
201
            params[:headers]['Transfer-Encoding'] = 'chunked'
 
202
          elsif ! (params[:method].to_s.casecmp('GET') == 0 && params[:body].nil?)
179
203
            # The HTTP spec isn't clear on it, but specifically, GET requests don't usually send bodies;
180
204
            # if they don't, sending Content-Length:0 can cause issues.
181
 
            unless (params[:method].to_s.casecmp('GET') == 0 && params[:body].nil?)
182
 
              params[:headers]['Content-Length'] = case params[:body]
183
 
              when File
184
 
                params[:body].binmode
185
 
                File.size(params[:body])
186
 
              when String
187
 
                if FORCE_ENC
188
 
                  params[:body].force_encoding('BINARY')
189
 
                end
190
 
                params[:body].length
191
 
              else
192
 
                0
193
 
              end
194
 
            end
 
205
            params[:headers]['Content-Length'] = detect_content_length(params[:body])
195
206
          end
196
207
 
197
208
          # add headers to request
208
219
          socket.write(request)
209
220
 
210
221
          # write out the body
211
 
          unless params[:body].nil? || params[:body].empty?
 
222
          if params.has_key?(:request_block)
 
223
            while true
 
224
              chunk = params[:request_block].call
 
225
              if FORCE_ENC
 
226
                chunk.force_encoding('BINARY')
 
227
              end
 
228
              if chunk.length > 0
 
229
                socket.write(chunk.length.to_s(16) << CR_NL << chunk << CR_NL)
 
230
              else
 
231
                socket.write('0' << CR_NL << CR_NL)
 
232
                break
 
233
              end
 
234
            end
 
235
          elsif !params[:body].nil?
212
236
            if params[:body].is_a?(String)
213
 
              socket.write(params[:body])
 
237
              unless params[:body].empty?
 
238
                socket.write(params[:body])
 
239
              end
214
240
            else
 
241
              params[:body].binmode if params[:body].respond_to?(:binmode)
215
242
              while chunk = params[:body].read(CHUNK_SIZE)
216
243
                socket.write(chunk)
217
244
              end
219
246
          end
220
247
 
221
248
          # read the response
222
 
          response = Excon::Response.parse(socket, params, &block)
 
249
          response = Excon::Response.parse(socket, params)
223
250
 
224
251
          if response.headers['Connection'] == 'close'
225
252
            reset
243
270
    end
244
271
 
245
272
    def invoke_stub(params)
246
 
      block_given = block_given?
247
273
      params[:captures] = {:headers => {}} # setup data to hold captures
248
274
      for stub, response in Excon.stubs
249
275
        headers_match = !stub.has_key?(:headers) || stub[:headers].keys.all? do |key|
276
302
            response
277
303
          end
278
304
 
279
 
          # don't pass stuff into a block if there was an error
280
305
          if params[:expects] && ![*params[:expects]].include?(response_attributes[:status])
281
 
            block_given = false
282
 
          end
283
 
 
284
 
          if block_given && response_attributes.has_key?(:body)
 
306
            # don't pass stuff into a block if there was an error
 
307
          elsif params.has_key?(:response_block) && response_attributes.has_key?(:body)
285
308
            body = response_attributes.delete(:body)
286
309
            content_length = remaining = body.bytesize
287
310
            i = 0
288
311
            while i < body.length
289
 
              yield(body[i, CHUNK_SIZE], [remaining - CHUNK_SIZE, 0].max, content_length)
 
312
              params[:response_block].call(body[i, CHUNK_SIZE], [remaining - CHUNK_SIZE, 0].max, content_length)
290
313
              remaining -= CHUNK_SIZE
291
314
              i += CHUNK_SIZE
292
315
            end