通过没有多部分装订线的 HTTP PUT 上传数据

Uploading data via HTTP PUT without multi-part gutter

我正在尝试将静态 HTML+朋友内容上传到原始 Nexus 3 存储库。就 the documentation goes 而言,上传文件的唯一方法是使用 HTTP PUT。果然,

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

按预期工作,可以在 http://my.nexus/repository/my-raw-repo/index.html

访问该文件

尽管如此,将此部署添加到我的 Rake 进程中却很麻烦。以下是我尝试过的一些方法。

  1. 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
    

    我尝试了 <snip> 的几种变体。

    1. 将正文设置为字符串形式的文件内容:

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

      请求完成且没有错误,但 Nexus 显示文件大小为 0 字节。

    2. 将表单数据作为流发送到文件内容:

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

      一个很明显:添加了 Nexus 不会删除的多部分装订线:

  2. 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
    

    对于 <snip>(猜测不太清楚的文档):

    1. body: File.read("#{file}")
      --> 0 字节。
    2. payload: File.read("#{file}")
      --> 0 字节。
    3. payload: { file: File.new("#{file}") }
      --> 多部分排水沟仍然存在。
    4. payload: { multipart: false, file: File.new("#{file}") }
      --> 多部分排水沟仍然存在。

    我想我尝试了几个我不记得的组合,结果相似。

注意好处:我省略了与使用自签名证书的 SSL 相关的部分,因为那应该是无关的。

我如何告诉任一库(或任何其他库)对数据进行 PUT 而不是多部分?或者,如果这不是问题所在,我做错了什么?

我想使用全 Ruby 解决方案(即不委托给系统 curl),以便构建可以(尽可能)可移植(尽可能)。

使用net/http,将请求正文设置为流式文件内容:

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

仅从文件中确定正确的 MIME 类型本身就是一种冒险。