Module: Handsoap::Http
- Defined in:
- lib/handsoap/http.rb
Overview
The Handsoap::Http module provides a uniform interface to various http drivers.
Defined Under Namespace
Modules: Curb, Httpclient, NetHttp Classes: HttpMock, Part, Request, Response
Constant Summary collapse
- @@drivers =
{ :net_http => NetHttp, :curb => Curb, :httpclient => Httpclient }
Class Method Summary collapse
- .drivers ⇒ Object
- .normalize_header_key(key) ⇒ Object
-
.parse_headers(raw) ⇒ Object
lifted from webrick/httputils.rb.
-
.parse_http_part(headers, body, status = nil, content_type = nil) ⇒ Object
Parses a raw http response into a
ResponseorPartobject. -
.parse_multipart(boundary, content_io, content_length = nil) ⇒ Object
Parses a multipart http-response body into parts.
-
.parse_multipart_boundary(content_type) ⇒ Object
Content-Type header string -> mime-boundary | nil.
Class Method Details
.drivers ⇒ Object
425 426 427 |
# File 'lib/handsoap/http.rb', line 425 def self.drivers @@drivers end |
.normalize_header_key(key) ⇒ Object
415 416 417 |
# File 'lib/handsoap/http.rb', line 415 def self.normalize_header_key(key) key.split("-").map{|s| s.downcase.capitalize }.join("-") end |
.parse_headers(raw) ⇒ Object
lifted from webrick/httputils.rb
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/handsoap/http.rb', line 386 def self.parse_headers(raw) header = Hash.new([].freeze) field = nil raw.gsub(/^(\r\n)+|(\r\n)+$/, '').each {|line| case line when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om field, value = $1, $2 field.downcase! header[field] = [] unless header.has_key?(field) header[field] << value when /^\s+(.*?)\s*\z/om value = $1 unless field raise "bad header '#{line.inspect}'." end header[field][-1] << " " << value else raise "bad header '#{line.inspect}'." end } header.each {|key, values| values.each {|value| value.strip! value.gsub!(/\s+/, " ") } } header end |
.parse_http_part(headers, body, status = nil, content_type = nil) ⇒ Object
Parses a raw http response into a Response or Part object.
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/handsoap/http.rb', line 264 def self.parse_http_part(headers, body, status = nil, content_type = nil) if headers.kind_of? String headers = parse_headers(headers) end if content_type.nil? && headers['content-type'] content_type = headers['content-type'].first end boundary = parse_multipart_boundary(content_type) parts = if boundary parse_multipart(boundary, body).map {|raw_part| parse_http_part(raw_part[:head], raw_part[:body]) } end if status.nil? Handsoap::Http::Part.new(headers, body, parts) else Handsoap::Http::Response.new(status, headers, body, parts) end end |
.parse_multipart(boundary, content_io, content_length = nil) ⇒ Object
Parses a multipart http-response body into parts. boundary is a string of the boundary token. content_io is either a string or an IO. If it’s an IO, then content_length must be specified. content_length (optional) is an integer, specifying the length of content_io
This code is lifted from cgi.rb
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/handsoap/http.rb', line 296 def self.parse_multipart(boundary, content_io, content_length = nil) if content_io.kind_of? String content_length = content_io.length content_io = StringIO.new(content_io, 'r') elsif !(content_io.kind_of? IO) || content_length.nil? raise "Second argument must be String or IO with content_length" end boundary = "--" + boundary quoted_boundary = Regexp.quote(boundary, "n") buf = "" bufsize = 10 * 1024 boundary_end = "" # start multipart/form-data content_io.binmode if defined? content_io.binmode boundary_size = boundary.size + "\r\n".size content_length -= boundary_size status = content_io.read(boundary_size) if nil == status raise EOFError, "no content body" elsif boundary + "\r\n" != status raise EOFError, "bad content body" end parts = [] loop do head = nil if 10240 < content_length require "tempfile" body = Tempfile.new("Handsoap") else begin require "stringio" body = StringIO.new rescue LoadError require "tempfile" body = Tempfile.new("Handsoap") end end body.binmode if defined? body.binmode until head and /#{quoted_boundary}(?:\r\n|--)/n.match(buf) if (not head) and /\r\n\r\n/n.match(buf) buf = buf.sub(/\A((?:.|\n)*?\r\n)\r\n/n) do head = $1.dup "" end next end if head and ( ("\r\n" + boundary + "\r\n").size < buf.size ) body.print buf[0 ... (buf.size - ("\r\n" + boundary + "\r\n").size)] buf[0 ... (buf.size - ("\r\n" + boundary + "\r\n").size)] = "" end c = if bufsize < content_length content_io.read(bufsize) else content_io.read(content_length) end if c.nil? || c.empty? raise EOFError, "bad content body" end buf.concat(c) content_length -= c.size end buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do body.print $1 if "--" == $2 content_length = -1 end boundary_end = $2.dup "" end body.rewind parts << {:head => head, :body => body.read(body.size)} break if buf.size == 0 break if content_length == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/ parts end |
.parse_multipart_boundary(content_type) ⇒ Object
Content-Type header string -> mime-boundary | nil
283 284 285 286 287 |
# File 'lib/handsoap/http.rb', line 283 def self.parse_multipart_boundary(content_type) if %r|\Amultipart.*boundary=\"?([^\";,]+)\"?|n.match(content_type) $1.dup end end |