0

I'm trying to upload static HTML+friends content to a raw Nexus 3 repository. As far as the documentation goes, the only way to upload files is using HTTP PUT. Sure enough,

curl -v --user 'user:pw' --upload-file my_file.html  \
    http://my.nexus/repository/my-raw-repo/my_file.html

works as expected and the file can be accessed at http://my.nexus/repository/my-raw-repo/index.html

Adding this deployment to my Rake process has turned out to be hasslesome, though. Here are some things I have tried.

  1. With net/http:

    require 'net/http'
    uri = URI("http://my.nexus/repository/my-raw-repo")
    file = "index.html"
    Net::HTTP.start(uri.host, uri.port) do |http|
        request = Net::HTTP::Put.new "#{repo_url}/#{file}"
        request.basic_auth(user, pw)
    
        <snip>
    
        response = http.request request
        raise "Upload failed: #{response.code} #{response.message}\n#{response.body}" \
           unless response.is_a?(Net::HTTPSuccess)
    end
    

    I tried several variants for <snip>.

    1. Set body to file content as string:

      request.body = File.read("#{file}")`
      

      Request completes without error but Nexus shows file size 0 bytes.

    2. Send form data to file content as stream:

      request.set_form([['upload', File.open("#{file}")]], 'multipart/form-data')
      

      That one is kind of obvious: multi-part gutter is added which Nexus does not remove:

      enter image description here

  2. With rest-client:

    require 'rest-client'
    file = "index.html"
    begin
        RestClient::Request.execute(
            method: :put,
            url: "http://my.nexus/repository/my-raw-repo/#{file}",
            <snip>
            user: user,
            password: pw
        )
    rescue RestClient::ExceptionWithResponse => e
        raise "Upload failed: #{e.response}"
    end
    

    And for <snip> (guessing around the less than clear documentation):

    1. body: File.read("#{file}")
      --> 0 bytes.
    2. payload: File.read("#{file}")
      --> 0 bytes.
    3. payload: { file: File.new("#{file}") }
      --> Multi-part gutter remains.
    4. payload: { multipart: false, file: File.new("#{file}") }
      --> Multi-part gutter remains.

    I think I tried several combination more which I don't remember, with similar results.

Note bene: I've left out the parts related to SSL with a self-signed certificate because that should be unrelated.

How can I tell either library (or any other) to do PUT with data but without multi-part? Or if that's not the issue, what am I doing wrong?

I want to use an all-Ruby solution (i.e. not delegate to system curl) so that the build can be (as) portable (as possible).

1 Answer 1

0

With net/http, set the request body to the file content as stream:

request.body_stream = File.open("#{file}")
request.content_length = File.size("#{file}")
request.content_type = "text/plain" # ?!

Determining the proper MIME type from the file alone is an adventure in itself.

1
  • I missed this due do idiocy (I had File.read and noticed only when writing up the question); I'd still appreciate an answer for rest-client since it has the nicer interface.
    – Raphael
    Commented May 13, 2019 at 12:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.