require'net/http'require'tempfile'require'shellwords'moduleCucumbermoduleFormatterclassHTTPIOclass<<self# Returns an IO that will write to a HTTP request's body# https_verify_mode can be set to OpenSSL::SSL::VERIFY_NONE# to ignore unsigned certificate - setting to nil will verify the certificatedefopen(url,https_verify_mode=nil,reporter=nil)@https_verify_mode=https_verify_modeuri,method,headers=CurlOptionParser.parse(url)IOHTTPBuffer.new(uri,method,headers,https_verify_mode,reporter)endendendclassCurlOptionParserdefself.parse(options)args=Shellwords.split(options)url=nilhttp_method='PUT'headers={}untilargs.empty?arg=args.shiftcaseargwhen'-X','--request'http_method=remove_arg_for(args,arg)when'-H'header_arg=remove_arg_for(args,arg)headers=headers.merge(parse_header(header_arg))elseraiseStandardError,"#{options} was not a valid curl command. Can't set url to #{arg} it is already set to #{url}"ifurlurl=argendendraiseStandardError,"#{options} was not a valid curl command"unlessurl[url,http_method,headers]enddefself.remove_arg_for(args,arg)returnargs.shiftunlessargs.empty?raiseStandardError,"Missing argument for #{arg}"enddefself.parse_header(header_arg)parts=header_arg.split(':',2)raiseStandardError,"#{header_arg} was not a valid header"unlessparts.length==2{parts[0].strip=>parts[1].strip}endendclassIOHTTPBufferattr_reader:uri,:method,:headersdefinitialize(uri,method,headers={},https_verify_mode=nil,reporter=nil)@uri=URI(uri)@method=method@headers=headers@write_io=Tempfile.new('cucumber',encoding: 'UTF-8')@https_verify_mode=https_verify_mode@reporter=reporter||NoReporter.newenddefcloseresponse=send_content(@uri,@method,@headers)@reporter.report(response.body)@write_io.closereturnifresponse.is_a?(Net::HTTPSuccess)||response.is_a?(Net::HTTPRedirection)raiseStandardError,"request to #{uri} failed with status #{response.code}"enddefwrite(data)@write_io.write(data)enddefflush@write_io.flushenddefclosed?@write_io.closed?endprivatedefsend_content(uri,method,headers,attempt=10)content=(method=='GET'?StringIO.new:@write_io)http=build_client(uri,@https_verify_mode)raiseStandardError,"request to #{uri} failed (too many redirections)"ifattempt<=0req=build_request(uri,method,headers.merge('Content-Length'=>content.size.to_s))content.rewindreq.body_stream=contentbeginresponse=http.request(req)rescueSystemCallError# We may get the redirect response before pushing the file.response=http.request(build_request(uri,method,headers))endcaseresponsewhenNet::HTTPAcceptedsend_content(URI(response['Location']),'PUT',{},attempt-1)ifresponse['Location']whenNet::HTTPRedirectionsend_content(URI(response['Location']),method,headers,attempt-1)endresponseenddefbuild_request(uri,method,headers)method_class_name="#{method[0].upcase}#{method[1..].downcase}"req=Net::HTTP.const_get(method_class_name).new(uri)headers.eachdo|header,value|req[header]=valueendreqenddefbuild_client(uri,https_verify_mode)http=Net::HTTP.new(uri.hostname,uri.port)ifuri.scheme=='https'http.use_ssl=truehttp.verify_mode=https_verify_modeifhttps_verify_modeendhttpendendendend