Ruby Multipart Post/Put Request

I had to modify a client app to perform a multipart PUT request and ran into a few snags that I'd like to share. The first is that there isn't a single common way to do this in Ruby. Ruby has a Net::HTTP API but it operates at a primitive level and so a higher level API would be useful. I like using the RestClient gem, but the mainline version does not support multipart POST/PUT requests yet. There is a @technoweenie fork of the gem that does, however, it is based on an older version. The app I was modifying was not based on this fork which is missing some useful features such as logging. Enter @nickseiger's multipart-post gem which does just what I need. This gem provides some code that works with Net::HTTP and supports both mutlipart POST and PUT requests. However, it also requires working with Net::HTTP directly which isn't as easy to use as RestClient.

One problem I ran into was that Net::HTTP does not automatically detect the use of TLS/SSL and so you must explicitly tell it to use it. I found some other posts like this one. Basically, one needs to set the instance attribute Net::HTTP#use_ssl separately. My version of the code is below. This is part of a larger example on using the Kenai APIs which can be found within the kenaiapis examples repository.

class KenaiClient
  # Code that uses rest-client gem
  @host = "https://kenai.com"
  ...
  module MultipartClient
    require 'net/http/post/multipart'

    def wiki_image_client(project, image_filename)
      @url = URI.parse("#{@host}/api/projects/#{project}/features/wiki/images/#{image_filename}")
      @initial_headers = { "accept" => 'application/json' }
      self
    end

    def put(payload, additional_headers = {})
      req = Net::HTTP::Put::Multipart.new(@url.path, payload, @initial_headers.merge(additional_headers))
      req.basic_auth(@user, @password)
      http = Net::HTTP.new(@url.host, @url.port)
      if @url.port == 443
        http.use_ssl = true
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        unless @warning_printed
          puts "\\nwarning: peer certificate for #{@url.host} won't be verified"
          @warning_printed = true
        end
      end
      res = http.start do |http|
        http.request(req)
      end
      raise "Request failed with response: #{res}" unless Net::HTTPSuccess === res
    end
  end
  include MultipartClient
end
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

edwingo

Search

Categories
Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today