cfhttp and cfhttpparam in ColdFusion - coldfusion

I have some XMl data, I want to use the XML data to be posted to a scheduler job so using cfhttp and cfhttpparam. But for reason after running this code I was not able to schedule a job in one of my site. Tried all the options with formfields, url and xml with no success. I was saving all my data into a xml variable using cfsavecontent and using that variable to pass into cfhttparam value. Not sure what Am I doing wrong here. Here is the below code
<cfsavecontent variable="getAllValues">
<start_job job="/cf/ecs/get_ecspseg1_data">
<params>
<param name="1_script" value="#script#" />
<param name="2_login" value="#login#"/>
<param name="3_customer" value="#customer#"/>
<param name="4_account" value="#account#"/>
<param name="5_begdate" value="#begdate#"/>
<param name="6_enddate" value="#enddate#"/>
</params>
</start_job>
</cfsavecontent>
<cfhttp url="http://ecs" port="4444" username="test" authType = "BASIC" password="testing*1" method="post">
<cfhttpparam type="xml" name="testing" value="#ToString(getAllValues)#"/>
</cfhttp>
here is the updated code:
<cfsavecontent variable="getAllValues">
<start_job job="/cf/smartecs/get_pseg1_data">
<params>
<param name="1_script" value="#script#" />
<param name="2_login" value="#login#"/>
<param name="3_customer" value="#customer#"/>
<param name="4_account" value="#account#"/>
<param name="5_begdate" value="#begdate#"/>
<param name="6_enddate" value="#enddate#"/>
</params>
</start_job>
</cfsavecontent>
<cfhttp url="http://10.xxx.xxx.xxx" port="4444" username="myusername" authType = "BASIC" password="mypassword" method="post" >
<cfhttpparam type="header" name="Content-Type" value="application/octet-stream">
<cfhttpparam type="body" name="testing" value="#getAllValues#"/>
</cfhttp>

When using a different Port number we need to even keep a / at the end of the URL. When I kept that / at the end of the URL it worked like a charm. ColdFusion will not accept : in the URL.

Related

cfhttp returning a connection failure for a network url that a browser can reach via both http and https

I am using cfhttp to try to pull some json from one of our organizations APIs. I have the code working when trying to pull example json from one of our own servers, but when I point it to the API itself I receive a connection failure. This is the code:
<cfhttp method="get" url="http://[url]/api/menu">
<cfhttpparam type="URL" name="id" value="[guid]">
</cfhttp>
<cfset FileWrite("#application.tempDirPath#/temp.json", CFHTTP.FileContent)>
I have replaced the real values with [url] and [guid].
I have tried accessing this url in a browser at https://[url]/api/menu?id=[guid] and it works perfectly fine, indicating that my machine has no problem reaching that url. The url is a server in our network that I can access as long as I'm on the company VPN.
Things that I have tried:
The live code should point to https. I've tried both http and https.
I've tried hitting the home page at that same url and it also results in a connection failure, but works in a browser.
I've tried this same code with http://www.google.com, and that downloads the Google html without issue.
I've tried restarting ColdFusion and my machine.
I've tried disabling compression via headers:
<cfhttp method="get" url="http://[url]/api/menu">
<cfhttpparam type="header" name="Accept-Encoding" value="deflate;q=0" />
<cfhttpparam type="header" name="TE" value="deflate;q=0" />
<cfhttpparam type="URL" name="id" value="[guid]">
</cfhttp>
I do not have access to the target server. I can ask those who do have access for help, but their conclusion at this point is "this is a ColdFusion problem.", so I'm not sure how much help I can get. This makes it impossible for me to check for Firewall rules or user-agent restrictions; suggestions on ways to test for those things locally would be welcome.
Edit
Per comments on this question I determined that http is just redirecting to https at that address. So I followed the instructions provided at ColdFusion https connection failure to import the certificate. After doing so I followed the instructions to verify that the cert was imported successfully. I then restarted CF Server.
After that I ran my code again and dumped the cfhttp struct as a whole into the temp file. This was the result:
<?xml version="1.0" encoding="UTF-8"?>
<STRUCT ID="1">
<ENTRY NAME="Errordetail" TYPE="STRING">I/O Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</ENTRY>
<ENTRY NAME="Mimetype" TYPE="STRING">Unable to determine MIME type of file.</ENTRY>
<ENTRY NAME="Statuscode" TYPE="STRING">Connection Failure. Status code unavailable.</ENTRY>
<ENTRY NAME="Filecontent" TYPE="STRING">Connection Failure</ENTRY>
<ENTRY NAME="Responseheader" TYPE="STRUCT">
<STRUCT ID="2" />
</ENTRY>
<ENTRY NAME="Text" TYPE="BOOLEAN">true</ENTRY>
<ENTRY NAME="Charset" TYPE="STRING" />
<ENTRY NAME="Header" TYPE="STRING" />
</STRUCT>

404 Not Found error in SOAP web service request via CFHTTP

I am having a lot of trouble communicating with a web service for our membership database. I get a valid result from my SOAP envelope when using SoapUI. But when I try to send the same envelope using CFHTTP and CF9 (I know, I know), I get a "404 Not Found" error no matter what I try to do. Accessing the URL in a browser gives me an "access denied" error.
Here is what I have in cfsavecontent:
<cfsavecontent variable="soapBody">
<cfoutput>
<?xml version=“1.0” encoding=“utf-8”?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://membersuite.com/schemas" xmlns:con="http://membersuite.com/contracts">
<soapenv:Header>
<sch:ConciergeRequestHeader>
<!--Optional:-->
<sch:BrowserId></sch:BrowserId>
<!--Optional:-->
<sch:SessionId></sch:SessionId>
<sch:AccessKeyId>MyAccessKey</sch:AccessKeyId>
<!--Optional:-->
<sch:AssociationId>MyAssociationID</sch:AssociationId>
<sch:Signature>MySignature</sch:Signature>
</sch:ConciergeRequestHeader>
</soapenv:Header>
<soapenv:Body>
<con:LoginToPortal>
<!--Optional:-->
<con:portalUserName>username</con:portalUserName>
<!--Optional:-->
<con:portalPassword>password</con:portalPassword>
</con:LoginToPortal>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
And here is my cfhttp:
<cfhttp url="https://soap.membersuite.com/mex" method="post" useragent="#CGI.http_user_agent#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="header" name="mimetype" value="application/xml" />
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="http://membersuite.com/contracts/IConciergeAPIService/LoginToPortal" />
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="header" name="content-length" value="#len(trim(soapBody))#">
<cfhttpparam type="xml" name="soapenv" value="#trim(soapBody)#" />
</cfhttp>
Dumping cfhttp gives me this error:
It seems obvious to me that the remote server is telling me it cannot find what I am asking it for. But it is the right endpoint, and I can see it in the WSDL:
<wsdl:operation name="LoginToPortal">
<wsdl:input wsaw:Action="http://membersuite.com/contracts/IConciergeAPIService/LoginToPortal" message="tns:IConciergeAPIService_LoginToPortal_InputMessage"/>
<wsdl:output wsaw:Action="http://membersuite.com/contracts/IConciergeAPIService/LoginToPortalResponse" message="tns:IConciergeAPIService_LoginToPortal_OutputMessage"/>
</wsdl:operation>
I have also added the SSL cert from the web service page to my CF keystone; no change in error message. I am at my wit's end and would appreciate any suggestions! Again, I am getting expected results back via SoapUI. Thank you all very much!
Going strictly off the SoapUI request, it seems to work if the target URL is changed to https://soap.membersuite.com/. Using bogus credentials, the response changes to "Invalid Access Key ID specified" instead of 404.
<cfhttp url="https://soap.membersuite.com/" method="post" useragent="#CGI.http_user_agent#">
<cfhttpparam type="header" name="Content-Type" value="text/xml; charset=utf-8" />
<cfhttpparam type="header" name="SOAPAction" value="http://membersuite.com/contracts/IConciergeAPIService/LoginToPortal" />
<cfhttpparam type="header" name="Accept-Encoding" value="no-compression" />
<cfhttpparam type="header" name="Content-Length" value="#len(trim(soapBody))#">
<cfhttpparam type="body" value="#trim(soapBody)#" />
</cfhttp>

Failure calling API with CFHTTP

I'm trying to pass some XML with cfhttp as follows to an API :
<cfxml variable="elementvalue">
<entry name='DENY_TEST'>
<to>
<member>Public</member>
</to>
<from>
<member>VPN_CLIENTS</member>
</from>
<source>
<member>any</member>
</source>
<destination>
<member>any</member>
</destination>
<source-user>
<member>any</member>
</source-user>
<category>
<member>any</member>
</category>
<application>
<member>bittorrent</member>
<member>skype</member>
</application>
<service>
<member>application-default</member>
</service>
<hip-profiles>
<member>any</member>
</hip-profiles>
<action>deny</action>
<rule-type>universal</rule-type>
<disabled>no</disabled>
</entry>
</cfxml>
This is the cfhttp call that I attempted:
<cfhttp method="post" url="https://domain.com/api" result="objGet" throwonerror="Yes">
<cfhttpparam name="type" type="formfield" value="config" />
<cfhttpparam name="action" type="formfield" value="set" />
<cfhttpparam name="key" type="formfield" value="LUZReHB3TVlyYrODNENGVpRmYvVmEvWW5uVjBzZHo4cz0=" />
<cfhttpparam name="xpath" type="formfield" value="/config/devices/entry[#name='localhost.localdomain']/vsys/entry[#name='vsys1']/rulebase/security/rules" />
<cfhttpparam name="element" type="formfield" value="#elementvalue#" />
</cfhttp>
If I use this in a browser everything works fine and I get success.
https://domain.com/api/?type=config&action=set&key=LUZReHB3TVlyYrODNENGVpRmYvVmEvWW5uVjBzZHo4cz0=&xpath==/config/devices/entry[#name='localhost.localdomain']/vsys/entry[#name='vsys1']/rulebase/security/rules&element=<entry name="DENY_TEST"><to><member>Public</member></to><from><member>VPN_CLIENTS</member></from><source><member>any</member></source><destination><member>any</member></destination><source-user><member>any</member></source-user><category><member>any</member></category><application><member>bittorrent</member><member>skype</member></application><service><member>application-default</member></service><hip-profiles><member>any</member></hip-profiles><action>deny</action><rule-type>universal</rule-type><disabled>no</disabled></entry>
Any idea why this could be failing? It is stopping at element. Am I right in using cfxml for this or should I try using a variable with backslashes?
The problem was with the ssl certificate on the device. It didn't occur to me to test it with http first. To use ssl I had to import the device's certificate in CF's keystore. I also used the following to store xml in a variable:
<cfsavecontent variable="elementvalue"><entry name='DENY_TEST'>
<to>
<member>Public</member>
</to>
<from>
<member>VPN_CLIENTS</member>
</from>
<source>
<member>any</member>
</source>
<destination>
<member>any</member>
</destination>
<source-user>
<member>any</member>
</source-user>
<category>
<member>any</member>
</category>
<application>
<member>bittorrent</member>
<member>skype</member>
</application>
<service>
<member>application-default</member>
</service>
<hip-profiles>
<member>any</member>
</hip-profiles>
<action>deny</action>
<rule-type>universal</rule-type>
<disabled>no</disabled>
</entry>
</cfsavecontent>

Passing a parameter in CFHTTP URL string

I am using cfhttp to post a series of user supplied parameters to an API. I am passing all of the parameters with <cfhttparam> except one: {myID}. Since the {myID} value will also be supplied by the user, I am wondering how can I make sure it gets passed inside the URL string?
<cfhttp url="http://abc.xyz.com/webservice/{myID}/add/multiple"
method="POST" result="returnStruct" >
<cfhttpparam name="Accept" type="header" value="application/json" />
<cfhttpparam type="header" name="datetime" value="#datetime#" />
<cfhttpparam type="header" name="authorization" value="#authorization#" />
<cfhttpparam type="formfield" name="myAPI" value="1" />
<cfhttpparam type="formfield" name="param1" value="1000" />
<cfhttpparam type="formfield" name="param2" value="myname#email.com" />
<cfhttpparam type="formfield" name="param3" value="2" />
<cfhttpparam type="formfield" name="param4" value="Tester" />
</cfhttp>
The client aplication should have the user's data from a previous request, if you pass it like
http://abc.xyz.com/webservice/user_id/add/multiple the server assumes that user_id is the parameter you call {myID}
Good luck

ColdFusion soap client

The following is a sample SOAP 1.2 request and response. The placeholders shown need to be replaced with actual values.
POST /CommunicationOfficeService1_0/CompanyAccountXmlService.asmx HTTP/1.1
Host: webservices.nbs.rs
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<AuthenticationHeader xmlns="http://communicationoffice.nbs.rs">
<UserName>string</UserName>
<Password>string</Password>
<LicenceID>guid</LicenceID>
</AuthenticationHeader>
</soap12:Header>
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumber xmlns="http://communicationoffice.nbs.rs">
<nationalIdentificationNumber>long</nationalIdentificationNumber>
</GetCompanyAccountByNationalIdentificationNumber>
</soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumberResponse xmlns="http://communicationoffice.nbs.rs">
<GetCompanyAccountByNationalIdentificationNumberResult>string</GetCompanyAccountByNationalIdentificationNumberResult>
</GetCompanyAccountByNationalIdentificationNumberResponse>
</soap12:Body>
</soap12:Envelope>
I have generated the ColdFusion code that looks like this
<cfsavecontent variable="soapBody">
<cfoutput>
POST /CommunicationOfficeService1_0/CompanyAccountXmlService.asmx HTTP/1.1
Host: webservices.nbs.rs
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<AuthenticationHeader xmlns="http://communicationoffice.nbs.rs">
<UserName>my_username</UserName>
<Password>my_password</Password>
<LicenceID>My_licence_id</LicenceID>
</AuthenticationHeader>
</soap12:Header>
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumber xmlns="http://communicationoffice.nbs.rs">
<nationalIdentificationNumber>20774550</nationalIdentificationNumber>
</GetCompanyAccountByNationalIdentificationNumber>
</soap12:Body>
</soap12:Envelope>
</cfoutput>
</cfsavecontent>
<!---
Now that we have our SOAP body defined, we need to post it as
a SOAP request to the Campaign Monitor website. Notice that
when I POST the SOAP request, I am NOT required to append the
"WSDL" flag to the target URL (this is only required when you
actually want to get the web service definition).
--->
<cfhttp
url="https://webservices.nbs.rs/CommunicationOfficeService1_0/CompanyAccountXmlService.asmx"
method="post"
result="httpResponse">
<!---
Most SOAP action require some sort of SOAP Action header
to be used.
--->
<cfhttpparam
type="header"
name="SOAPAction"
value="http://communicationoffice.nbs.rs/GetCompanyAccountByNationalIdentificationNumber"
/>
<!---
I typically use this header because CHTTP cannot handle
GZIP encoding. This "no-compression" directive tells the
server not to pass back GZIPed content.
--->
<cfhttpparam
type="header"
name="accept-encoding"
value="no-compression"
/>
<!---
When posting the SOAP body, I use the CFHTTPParam type of
XML. This does two things: it posts the XML as a the BODY
and sets the mime-type to be XML.
NOTE: Be sure to Trim() your XML since XML data cannot be
parsed with leading whitespace.
--->
<cfhttpparam
type="xml"
value="#trim( soapBody )#"
/>
</cfhttp>
<!---
When the HTTP response comes back, our SOAP response will be
in the FileContent atribute. SOAP always returns valid XML,
even if there was an error (assuming the error was NOT in the
communication, but rather in the data).
--->
<cfif find( "200", httpResponse.statusCode )>
<!--- Parse the XML SOAP response. --->
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<!---
Query for the response nodes using XPath. Because the
SOAP XML document has name spaces, querying the document
becomes a little funky. Rather than accessing the node
name directly, we have to use its local-name().
--->
<cfset responseNodes = xmlSearch(
soapResponse,
"//*[ local-name() = 'Subscriber.AddAndResubscribeResult' ]"
) />
<!---
Once we have the response node, we can use our typical
ColdFusion struct-style XML node access.
--->
<cfoutput>
Code: #responseNodes[ 1 ].Code.xmlText#
<br />
Success: #responseNodes[ 1 ].Message.xmlText#
</cfoutput>
</cfif>
I have none results . The web service uses this is the web site
This is the wsdl file
Serbian National Bank Web Service
How to make this web service run
I've modified a function I've used in the past to pass data form ColdFusion to Dynamics GP via soap.
<cffunction name="callWebService" access="public" output="false">
<cfargument name="soap" type="xml" required="true">
<cfhttp url="https://webservices.nbs.rs/CommunicationOfficeService1_0/CompanyAccountXmlService.asmx" method="post">
<cfhttpparam type="header" name="content-type" value="application/soap+xml">
<cfhttpparam type="header" name="SOAPAction" value="http://communicationoffice.nbs.rs/GetCompanyAccountByNationalIdentificationNumber">
<cfhttpparam type="header" name="accept-encoding" value="no-compression">
<cfhttpparam type="header" name="content-length" value="#len(Arguments.soap)#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="xml" name="message" value="#trim(Arguments.soap)#">
</cfhttp>
<cfreturn Trim(cfhttp.FileContent)>
</cffunction>
I believe I've updated the <cfhttpparam />s necessary for the web service you've linked. I would recommend using a software called SOAP UI to test your connection to the service and SOAP XML body outside of ColdFusion. In my above function, the argument soap would be your saved content "soapBody".
One thing needs to be fixed in your soapBody. The text prior to the start of XML is information regarding data that needs to be in the HTTP header, and I've only seen these values imputed as <cfhttpparam />.
The reason I think you may not be getting the desired 200 response with your above code is that the XML body is incorrectly formatted with the WSDL HTTP header example text. I also did not see the length of the body being declared as well.
While trying to set up your connection try just dumping httpResponse out until you start seeing valid soap responses from the server.