Trying to Post an xml document to a server - ruby-on-rails

I'm on an mission create an XML file and then POST this file to a server address. However I cant crack why it wont send, im currently stuck getting a "TypeError in CatalogController#gen_xml" > "String can't be coerced into Integer".
However im quite new to this and dont fully grasp to how to best execute this. Any help would be greatly appreciated!
Controller
class CatalogController < ApplicationController
require "builder/xmlmarkup"
require 'builder'
require 'rubygems'
require 'net/http'
def gen_xml
#xml = Builder::XmlMarkup.new
#catalogs=Catalog.all
url = "https://xxx.xxxx.com/xxxCXMLxx.aw/xx/cxml";
request = Net::HTTP::Post.new(url)
#request.add_field "Content-Type", "application/xml"
request.body = #xml
url = URI.parse(url)
req = Net::HTTP::Post.new(url.request_uri)
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = (url.scheme == "https")
#response = http.request(req)
response = http.post(url, #xml, initheader = {'Content-Type' =>'text/xml'})
end
end
View with Button to call method
Super cXML Generator!
<%= form_tag catalog_gen_xml_path, method: :post do %>
<%= submit_tag 'Call Action' %>
<% end %>
Routes File
Rails.application.routes.draw do
get 'catalog/gen_xml'
post 'catalog/gen_xml'
end
Error Trace
Extracted source (around line #24):
22 http.use_ssl = (url.scheme == "https")
23 #response = http.request(req)
24 response = http.post(url, #xml, initheader = {'Content-Type' =>'text/xml'})
25 end
26 end
27
app/controllers/catalog_controller.rb:24:in `gen_xml'
Rails.root: /Users/i303072/railsapps/xmlbuilder
XML Builder File - gen_xml.builder
#xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
#xml_markup.declare! :DOCTYPE, :chapter, :SYSTEM, "../dtds/chapter.dtd"
xml.cXML(:payloadID=>"XX", :timestamp=>"2018-03-11T11:28:01-07:00", :version=>"1.2.029", :xmllang=>"en-US") {
xml.Header {
xml.From {
xml.Credential(:domain=>"ID") {
xml.Identity "AN-T"
}#Credential
}#From
xml.To {
xml.Credential(:domain=>"ID") {
xml.Identity "AV-T"
}#Credential
xml.Correspondent{
xml.Contact(:role=>"correspondent") {
xml.Name("MRO", "xml:lang" => "en")
xml.PostalAddress{
xml.Country("US", "isoCountryCode" => "US")
}#PostalAddress
}#Contact
}#Correspondent
}#To
xml.Sender {
xml.Credential(:domain=>"NetworkID") {
xml.Identity "AN-T"
xml.SharedSecret "xxx"
}#Credential
xml.UserAgent "xxx"
}#Sender
} #Header
xml.Message(:deploymentMode=>"test") {
xml.ProductActivityMessage(:subcontractingIndicator=>"yes") {
xml.ProductActivityHeader(creationDate: "2018-03-13T22:00:00-08:00", messageID: "Cxxx")
}#ProductivityActivityMessage
}#Message
}#cXML

Related

How to call JDoodle API from local Rails server?

I am calling the JDoodle API with post request from my local machine Rails server with valid id and secrete. I am not getting desired response. Please suggest me if i am doing wrong....
My Ruby function to make api call
def run_Jddodle_API
require 'net/http'
require 'uri'
require 'json'
uri = URI.parse("https://api.jdoodle.com/v1/execute")
request = Net::HTTP::Post.new(uri)
request.content_type = "application/json; charset=UTF-8"
request.body = {
"clientId" => "ddc371fd*************c8efbae",
"clientSecret" => "4ee8e79a225***************************a8ee7f331aeeca603",
"script" => "<?php printf(\"hello RAJA\"); ?>",
"language" => "php",
"versionIndex" => "0"
}.to_json
req_options = { use_ssl: uri.scheme == "https", }
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
puts response.body
end
And the response is
{"error":"Unauthorized Request","statusCode":401}
try changing this line:
request.content_type = "application/json; charset=UTF-8"
to this:
request.content_type = "application/json"
I changed the code as below and it worked but can't say why.?
require 'uri'
require 'net/http'
require 'net/https'
url = URI("https://api.jdoodle.com/v1/execute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url.path)
request["Content-Type"] = 'application/json'
request.body = {
"script" => params[:code],
"language" => params[:lang],
"versionIndex" => params[:version],
"clientId" => "dc37******************efbae",
"clientSecret" => "4ee8e79a225a5525*******************************************"
}.to_json
response = http.request(request)
puts response.read_body`

Issue regarding http POST api call using ruby code

I am going to access the Riskscreen api to authenticate users. To test the api I have written a ruby code snippet to make sample POST call to get the number of tokens I have from the Riskscreen api.
My code is:
require 'uri'
require 'net/http'
require 'net/https'
require 'json'
#toSend = {}.to_json
uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
header = {'api-key': 'my api key','Content-Type': 'application/json', 'Accept': 'application/json'}
req = Net::HTTP::Post.new(uri.path, header)
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "------------"
puts "Response #{res.code} #{res.message}: #{res.body}"
But I am getting the following error:
Response 400 Bad Request
If I change the header line to
header = {'api-key'=> 'my-api-key','Content-Type'=> 'application/json', 'Accept'=> 'application/json'}
then I am getting this error:
Response 401 Unauthorized
Sticking with this for a while. Please help me to sort out this.
Header's keys must be String instead of Symbol
header = {'api-key' => 'my api key','Content-Type' => 'application/json', 'Accept' => 'application/json'}
Another issue is net/http is capitalize header automatically, api-key -> Api-Key which cause Authorization Error on your server. One solution is to create new class to wrap api-key to prevent Ruby do that
class HeaderCaseSensitive < String
def capitalize
self
end
def split(*args)
super.each do |str|
HeaderCaseSensitive.new(str)
end
end
def to_s
self
end
end
Then change header:
header = {HeaderCaseSensitive.new('api-key') => 'xxxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
To sum up, following code will work:
require 'uri'
require 'net/http'
require 'net/https'
require 'json'
class HeaderCaseSensitive < String
def capitalize
self
end
def split(*args)
super.each do |str|
HeaderCaseSensitive.new(str)
end
end
def to_s
self
end
end
#toSend = {}.to_json
uri = URI.parse("https://api.riskscreen.com/api/v1/user/tokens")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
header = {HeaderCaseSensitive.new('api-key') => 'xxx','Content-Type' => 'application/json', 'Accept' => 'application/json'}
https.set_debug_output($stdout)
req = Net::HTTP::Post.new(uri.path, header)
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "------------"
puts "Response #{res.code} #{res.message}: #{res.body}"
Can you try remove:
req.body = "[ #{#toSend} ]"
and replace by:
req.set_form_data({})
# or
req.body = "{}"
Sorry, I'm not sure about that.

Rails - net/http is working but same request is not working in httparty

I'm trying to do a request in httparty but it's not working
require 'httparty'
module PvWatch
class Client
include HTTParty
# base_uri ENV["pv_watch_endpoint"]
def login
response = self.class.post('http://pvwatch.xxx.xxx.xxx.net/api/v1/login', options)
end
def options
{
headers: {
'content-type' => 'application/json',
'access-key' => 'FORGET ABOUT THIS',
'authorization' => 'uri=api/v1/login'
},
body: {
username: "case",
password: "123"
}
}
end
end
end
the weird thing is that when i do the request with net/http is working and i don't know what i'm doing wrong with httparty
require 'uri'
require 'net/http'
module PvWatch
class Client
def login
url = URI("http://pvwatch.xxx.xxx.xxx.net/api/v1/login")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/x-www-form-urlencoded'
request["access-key"] = 'FORGET ABOUT THIS'
request["authorization"] = 'uri=api/v1/login'
request.body = "username=case&password=123"
response = http.request(request)
puts response.read_body
end
end
end
any idea what i'm doing wrong?

how to upload pdf file along with SOAP API as multipart/form-data post in rails 4 + savon

Requirement: Response of "transaction_id" from the API and while uploading parameters,we also required to pass a pdf file along with this API,but there is no parameter to send file with the API.So we are doing like this in our model as multipart/form-data to http request.
http://xyz.xyz.com/xyz/upload.ashx?u=username&p=passwordtid=ticketGuid
User name "xxxxxxx"
Password "yyyyyy"
tid "f155a1e5-d1cd-4edb-8d25-89f3852a06f4"
Response required is TransID(decimal)
Our model code is below,
require "net/http"
class Job < ActiveRecord::Base
after_update :upload_ticket_file
has_attached_file :ad_pdf
validates_attachment_content_type :ad_pdf, :content_type => "application/pdf"
validates_attachment :ad_pdf, :presence => true
validates :section_id, :section, :colour_id, :colour, :size_id, :sizes, :height, :width, :height_bleed, :width_bleed, :booking_number, :presence => true
def generate_xml_ticket
"<?xml version='1.0' encoding='UTF-8'?><env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ads='http://adstream.com/' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:Body><ads:AddTicketToPool><ads:XMLTicket><![CDATA[<?xml version='1.0' encoding='utf-8'?><jobbag><jobentry><colour_name /><page_setup><bleed_depth>#{(self.height_bleed.to_f*2.83).round(2)}</bleed_depth><bleed_width>#{(self.width_bleed.to_f*2.83).round(2)}</bleed_width><trim_depth>#{(self.height.to_f*2.83).round(2)}</trim_depth><trim_width>#{(self.width.to_f*2.83).round(2)}</trim_width></page_setup><named_size>#{self.sizes.split('/').last}</named_size><number_of_columns>#{self.size_number_of_columns}</number_of_columns><publication_code>#{self.publication_code}</publication_code><publisher_code>#{PUBLISHER[:code]}</publisher_code><section_code>#{self.section.split('/')[1]}</section_code><style>3</style><attention/><instructions /><booking_number pscode='BkNo' psformat='pZ1F' pstitle='Booking #' pstype='1'>#{self.booking_number}</booking_number><publication_date pscode='RnDt' psformat='yZ00' pstitle='Publicaiton Date' pstype='1'>#{self.issue_date.strftime("%d-%b-%Y")}</publication_date><caption /><insertion_number/><production_key /><customer_name pscode='ACNm' psformat='sZ00' pstitle='Ad Client Name' pstype='1'>#{PUBLISHER[:company_name].to_s}</customer_name><any pscode='APro' psformat='NZ00' pstitle='Brand' pstype='1'>#{self.brand}</any><any pscode='Camp' psformat='nZ00' pstitle='Campaign' pstype='1'>#{self.campaign}</any><any pscode='Rpla' psformat='bP00' pstitle='Replacement Material' pstype='1'>false</any><any pscode='Hard' psformat='BP00' pstitle='Hard Proof Sent' pstype='1'>false</any></jobentry><job_common><operator>#{self.attention_to}</operator><file_name>#{self.ad_pdf_file_name}</file_name></job_common></jobbag>]]></ads:XMLTicket></ads:AddTicketToPool></env:Body></env:Envelope>"
end
def upload_ticket_file
# response = system("curl -v -F media=##{self.ad_pdf.path} -F message='#{self.ad_pdf_file_name}' '#{ADSTREAM_QPWEB_UPLOAD_URL}?u=#{ADSTREAM_QPWEB_USERNAME}&p=#{ADSTREAM_QPWEB_PASSWORD}&tid=#{self.ticket_guid}'"
# uri = URI.parse(ADSTREAM_QPWEB_UPLOAD_URL+"?u=#{ADSTREAM_QPWEB_USERNAME_ENCODED}&p=#{ADSTREAM_QPWEB_PASSWORD}&tid=#{self.ticket_guid}")
boundary = "ABASDASDSAKJDFKDFNDKFDKFJDKNDFDN"
uri = URI.parse(ADSTREAM_QPWEB_UPLOAD_URL+"?u=#{ADSTREAM_QPWEB_USERNAME_ENCODED}&p=#{ADSTREAM_QPWEB_PASSWORD}&tid=#{self.ticket_guid}")
puts ">>>>>>>>>>>>>>>>>>>>>>>>>"
puts ADSTREAM_QPWEB_UPLOAD_URL+"?u=#{ADSTREAM_QPWEB_USERNAME_ENCODED}&p=#{ADSTREAM_QPWEB_PASSWORD}&tid=#{self.ticket_guid}"
file = self.ad_pdf.path
post_body = []
post_body << "Content-Disposition: form-data; name='datafile'; filename='#{self.ad_pdf_file_name}'"
post_body << "Content-Type: application/pdf"
post_body << File.read(file)+boundary
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.body = post_body.join
request["Content-Type"] = "multipart/form-data"
request.add_field('session', boundary)
response = http.request(request)
puts request.inspect
puts response.inspect
if response and (response.body != "ticketnotaddedtostore" and !response.body.to_s.blank? and response.body != "incorrectquerystrings")
if self.update_attribute(:transaction_id, response.body)
client = Savon.client(namespace_identifier: :ads) do
wsdl ADSTREAM_QPWEB_URL
log true
end
message = {TransID: self.transaction_id}
response = client.call(:check_status) do
message (message)
end
self.update_attribute(:check_status_result, response.body.to_hash[:check_status_response][:check_status_result])
end
end
end
end
class JobXMLTicket
def to_s
builder = Builder::XmlMarkup.new
builder.instruct!(:xml, encoding: "UTF-8")
builder.jobbag { |jo|
jo.jobentry { |je|
je.colour_name
je.page_setup {|ps|
ps.bleed_depth "0.0"
ps.bleed_width "0.0"
ps.trim_depth "725.66"
ps.trim_width "1150.86"
}
}
}
builder
end
end
Using 'RestClient gem' we can do the needful
require "net/http"
require 'savon'
require 'rest_client'
$config = {
qpweb_upload_url: 'http://example.com/WebAPI/upload.ashx'
}
class Job < ActiveRecord::Base
def uploadPdf
q = URI.encode_www_form( {
:u => USERNAME,
:p => PASSWORD,
:tid => ticket_guid
})
response = RestClient.post( $config[:qpweb_upload_url] + '?' + q, :file =>File.open(self.ad_pdf.path, 'rb') )
id = /transid=(.*)/.match( response.to_str )
raise 'error uploading file' if !id
puts 'TransactionId: ', id[1]
return id[1]
end
end

Trouble when fileupload form_tag rails

I have the trouble when I use form_tag for fileupload via POST query to API.
When I use:
= form_tag("http://myapi.com/api/images/user/#{#user_id}", multipart: true) do
= file_field_tag 'upload'
= submit_tag 'Upload avatar'
I have no troubles. But when I try to use the action for update_avatar, I have the trouble.
= form_tag({:action => 'upload_avatar'}, multipart: true) do
= file_field_tag 'upload'
= submit_tag 'Upload avatar'
update_avatar action code:
def upload_avatar
#user_id = params[:id]
#post_params = {'upload' => params[:upload]}
response, data = Net::HTTP.post_form(URI.parse("http://myapi.com/api/images/user/#{#user_id}"), #post_params)
redirect_to users_path
end
response is:
#<Net::HTTPInternalServerError:0x007f331486f4e0>
data is: nil
Here are 3 ways to upload file
require "net/http"
require "uri"
# Token used to terminate the file in the post body. Make sure it is not
# present in the file you're uploading.
BOUNDARY = "AaB03x"
uri = URI.parse("http://something.com/uploads")
file = "/path/to/your/testfile.txt"
post_body = []
post_body << "--#{BOUNDARY}\r\n"
post_body << "Content-Disposition: form-data; name=\"datafile\"; filename=\"#{File.basename(file)}\"\r\n"
post_body << "Content-Type: text/plain\r\n"
post_body << "\r\n"
post_body << File.read(file)
post_body << "\r\n--#{BOUNDARY}--\r\n"
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.body = post_body.join
request["Content-Type"] = "multipart/form-data, boundary=#{BOUNDARY}"
http.request(request)
# Alternative method, using Nick Sieger's multipart-post gem
require "rubygems"
require "net/http/post/multipart"
reqest = Net::HTTP::Post::Multipart.new uri.request_uri, "file" => UploadIO.new(file, "application/octet-stream")
http = Net::HTTP.new(uri.host, uri.port)
http.request(request)
# Another alternative, using Rack 1.3 +
require 'rack'
uri = URI.parse("http://something.com/uploads")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.body = Rack::Multipart::Generator.new(
"form_text_field" => "random text here",
"file" => Rack::Multipart::UploadedFile.new(path_to_file, file_mime_type)
).dump
request.content_type = "multipart/form-data, boundary=#{Rack::Multipart::MULTIPART_BOUNDARY}"
http.request(request)
http.start do |connection|
response = retrying_request(connection, request)
end

Resources