I am trying to use Curl::Easy.http_put but have some issues with the data argument

StackOverflow https://stackoverflow.com/questions/22384610

  •  14-06-2023
  •  | 
  •  

Question

I'm struggling with a ruby script to upload some pictures to moodstocks using their http interface

here is the code that I have so far

curb = Curl::Easy.new
curb.http_auth_types = :digest
curb.username = MS_API
curb.password = MS_SECRET
curb.multipart_form_post = true

Dir.foreach(images_directory) do |image|
  if image.include? '.jpg'
    path = images_directory + image
    filename = File.basename(path, File.extname(path))

    puts "Upload #{path} with id #{filename}"

    raw_url = 'http://api.moodstocks.com/v2/ref/' + filename
    encoded_url = URI.parse URI.encode raw_url

    curb.url = encoded_url
    curb.http_put(Curl::PostField.file('image_file', path))
  end
end

and this is the error that I get

/Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `add': no implicit        conversion of nil into String (TypeError)
    from /Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `perform'
    from upload_moodstocks.rb:37:in `http_put'
    from upload_moodstocks.rb:37:in `block in <main>'
    from upload_moodstocks.rb:22:in `foreach'
    from upload_moodstocks.rb:22:in `<main>'

I think the problem is in how I give the argument to the http_put method, but I have tried to look for some examples of Curl::Easy.http_put and have found nothing so far.

Could anyone point me to some documentation regarding it or help me out on this.

Thank you in advance

Était-ce utile?

La solution

There are several problems here:

1. URI::HTTP instead of String

First, the TypeError you encounter comes from the fact that you pass a URI::HTTP instance (encoded_url) as curb.url instead of a plain Ruby string.

You may want to use encoded_url.to_s, but the question is why do you do this parse/encode here?

2. PUT w/ multipart/form-data

The second problem is related to curb. At the time of writing (v0.8.5) curb does NOT support the ability to perform a HTTP PUT request with multipart/form-data encoding.

If you refer to the source code you can see that:

  1. the multipart_form_post setting is only used for POST requests,
  2. the put_data setter does not support Curl::PostField-s

To solve your problem you need an HTTP client library that can combine Digest Authentication, multipart/form-data and HTTP PUT.

In Ruby you can use rufus-verbs, but you will need to use rest-client to build the multipart body.

There is also HTTParty but it has issues with Digest Auth.

That is why I greatly recommend to go ahead with Python and use Requests:

import requests
from requests.auth import HTTPDigestAuth
import os

MS_API_KEY = "kEy"
MS_API_SECRET = "s3cr3t"

filename = "sample.jpg"

with open(filename, "r") as f:
  base = os.path.basename(filename)
  uid = os.path.splitext(base)[0]

  r = requests.put(
    "http://api.moodstocks.com/v2/ref/%s" % uid,
    auth = HTTPDigestAuth(MS_API_KEY, MS_API_SECRET),
    files = {"image_file": (base, f.read())}
  )

  print(r.status_code)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top