# frozen_string_literal: true require 'openssl' require 'net/http' require 'json' module Spout module Helpers class SendFile class << self def post(*args) new(*args).post end end attr_reader :url def initialize(url, filename, version, token, slug, folder) @params = {} @params['version'] = version @params['auth_token'] = token if token @params['dataset'] = slug if slug @params['folder'] = folder if folder begin file = File.open(filename, 'rb') @params['file'] = file mp = Multipart::MultipartPost.new @query, @headers = mp.prepare_query(@params) ensure file.close if file end begin @url = URI.parse(url) @http = Net::HTTP.new(@url.host, @url.port) if @url.scheme == 'https' @http.use_ssl = true @http.verify_mode = OpenSSL::SSL::VERIFY_NONE end rescue end end def post response = @http.start do |http| http.post(@url.path, @query, @headers) end JSON.parse(response.body) rescue nil end end end end module Multipart class Param attr_accessor :k, :v def initialize(k, v) @k = k @v = v end def to_multipart "Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n" end end class FileParam attr_accessor :k, :filename, :content def initialize(k, filename, content) @k = k @filename = filename @content = content end def to_multipart mime_type = 'application/octet-stream' "Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" + "Content-Transfer-Encoding: binary\r\n" + "Content-Type: #{mime_type}\r\n\r\n" + content + "\r\n" end end class MultipartPost BOUNDARY = 'a#41-93r1-^Õ-rule0000' HEADER = { 'Content-type' => "multipart/form-data, boundary=#{BOUNDARY} " } def prepare_query(params) fp = [] params.each do |k, v| if v.respond_to?(:read) fp.push(FileParam.new(k, v.path, v.read)) else fp.push(Param.new(k, v)) end end query = fp.collect { |p| "--#{BOUNDARY}\r\n" + p.to_multipart }.join('') + "--#{BOUNDARY}--" return query, HEADER end end end