REST Service returns CORS? error - ColdFusion - rest

I create a REST service in CF11 and up until last night everything was working fine until I started getting CORS errors all over the place.
Long story short this is my code:
<cfcomponent rest="true" restPath="/testimonials">
<cffunction name="getTestimonials" access="remote" returntype="any" httpMethod="GET" restPath="/getTestimonials">
<cfargument name="showRatings" type="numeric" restArgSource="Query" default="0">
<cfargument name="siteID" type="numeric" restArgSource="Query" default="0">
<cfargument name="pageID" type="numeric" restArgSource="Query" default="0">
.....
And I am calling it like this
<cfhttp url="http://dev.example.com/rest/api/testimonials/getTestimonials" method="GET" result="res">
<cfhttpparam type="URL" name="showRatings" value="0">
<cfhttpparam type="URL" name="siteID" value="17">
<cfhttpparam type="URL" name="pageID" value="2">
</cfhttp>
<cfdump var="#res#">
And this is the return struct that I am getting back
struct
Charset [empty string]
ErrorDetail [empty string]
Filecontent [empty string]
Header HTTP/1.1 200 OK Access-Control-Allow-Methods: POST,GET,OPTIONS Date: Wed, 23 Sep 2015 08:14:02 GMT Content-Length: 0 Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Origin: * Server: Microsoft-IIS/8.0 X-Powered-By: ASP.NET server-error: true
Mimetype Unable to determine MIME type of file.
Responseheader
struct
Access-Control-Allow-Headers Content-Type
Access-Control-Allow-Methods POST,GET,OPTIONS
Access-Control-Allow-Origin *
Content-Length 0
Date Wed, 23 Sep 2015 08:14:02 GMT
Explanation OK
Http_Version HTTP/1.1
Server Microsoft-IIS/8.0
Status_Code 200
X-Powered-By ASP.NET
server-error true
Statuscode 200 OK
Text YES
Nothing Changed as far as I know code-wise or on my IIS server to justify this error. I even added the code below in my web.config to try and enable CORS
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
<add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS"/>
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>

Related

How do I get the WSDL from this .asmx URL?

There's this web service I want to connect to. It's fully detailed here: https://simphonytsapi.docs.apiary.io/#reference/calculatetransactiontotals/overview/example-1?console=1
As you can see there's details on the right on how to connect to it. For example to call the CalculateTransactionTotals method of the web service there is:
This .asmx URL: https://private-102dc-simphonytsapi.apiary-mock.com/1/EGateway/SimphonyPosApiWeb.asmx
And these headers:
Content-Type text/xml;charset=UTF-8
SOAPAction http://micros-hosting.com/EGateway/CalculateTransactionTotals
And this example request body:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<CalculateTransactionTotals xmlns="http://micros-hosting.com/EGateway/">
<vendorCode />
<ppMenuItems />
<ppComboMeals>
<SimphonyPosApi_ComboMeal>
<ComboMealMainItem>
<Condiments />
<MenuItem>
<ItemDiscount>
<DiscObjectNum>0</DiscObjectNum>
</ItemDiscount>
<MiObjectNum>181020001</MiObjectNum>
<MiReference />
<MiWeight />
<MiMenuLevel>1</MiMenuLevel>
<MiSubLevel>1</MiSubLevel>
<MiPriveLevel>0</MiPriveLevel>
</MenuItem>
</ComboMealMainItem>
<ComboMealMenuItem>
<Condiments />
<MenuItem>
<ItemDiscount>
<DiscObjectNum>0</DiscObjectNum>
</ItemDiscount>
<MiObjectNum>181010001</MiObjectNum>
<MiReference />
<MiWeight />
<MiMenuLevel>1</MiMenuLevel>
<MiSubLevel>1</MiSubLevel>
<MiPriveLevel>0</MiPriveLevel>
</MenuItem>
</ComboMealMenuItem>
<ComboMealObjectNum>11</ComboMealObjectNum>
<SideItems>
<SimphonyPosApi_MenuItem>
<Condiments />
<MenuItem>
<ItemDiscount>
<DiscObjectNum>0</DiscObjectNum>
</ItemDiscount>
<MiObjectNum>181030001</MiObjectNum>
<MiReference />
<MiWeight />
<MiMenuLevel>1</MiMenuLevel>
<MiSubLevel>1</MiSubLevel>
<MiPriveLevel>0</MiPriveLevel>
</MenuItem>
</SimphonyPosApi_MenuItem>
<SimphonyPosApi_MenuItem>
<Condiments />
<MenuItem>
<ItemDiscount>
<DiscObjectNum>0</DiscObjectNum>
</ItemDiscount>
<MiObjectNum>299030001</MiObjectNum>
<MiReference />
<MiWeight />
<MiMenuLevel>1</MiMenuLevel>
<MiSubLevel>1</MiSubLevel>
<MiPriveLevel>0</MiPriveLevel>
</MenuItem>
</SimphonyPosApi_MenuItem>
</SideItems>
</SimphonyPosApi_ComboMeal>
</ppComboMeals>
<pSvcCharge>
<SvcChgObjectNum>0</SvcChgObjectNum>
</pSvcCharge>
<pSubtotalDiscount>
<DiscObjectNum>0</DiscObjectNum>
</pSubtotalDiscount>
<revenueCenter>11</revenueCenter>
<orderType>1</orderType>
<employeeNumber>900000092</employeeNumber>
<pTotalsResponse />
</CalculateTransactionTotals>
</soap:Body>
</soap:Envelope>
I need the WSDL to connect to this web service. How do I get it?

Why is a SOAP call working from CFM page but not from a CFC page?

I am working with a SOAP request in coldfusion. When the code I have is run from a .CFM file, it works. If it is run from a .CFC file, it doesn't work. The code is the same as far as possible (the .CFC needs the cfcomponent and cffunction tags for example).
Why would it work from one and not the other? When I call it from the CFC page I get the error
Does anyone have any idea why this might be happening? The SOAP request is identical on both pages. The call with the CFHTTP as well as all the CFHTTPPARAMs are the same as well.
Here is the code for the CFC file:
<cfcomponent>
<cffunction name="updateAgParcel" returntype="string" returnformat="plain" access="remote">
<cfargument name="ag_pres_nr" required="true" type="string">
<cfargument name="emp_nr" required="true" type="string">
<cfargument name="dt_rcvd" required="true" type="string">
<cfset dt_rcvd = DateFormat(#dt_rcvd#,"MMDDYYYY")>
<cfsavecontent variable="soapBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ass="http://XXXXXX">
<soapenv:Header/>
<soapenv:Body>
<ass:LogAgPreserveFiling>
<ass:AG.PRES.NR>#ag_pres_nr#</ass:AG.PRES.NR>
<ass:TC>04</ass:TC>
<ass:EMP.NR>#emp_nr#</ass:EMP.NR>
<ass:LCAQ.DT.RCVD>#dt_rcvd#</ass:LCAQ.DT.RCVD>
</ass:LogAgPreserveFiling>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp url="XXXXXXXXXXXXXXX" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="XXXXXXXXXXXX" />
<cfhttpparam type="header" name="Authorization" value="Basic XXXXXXXXXXXXXX" />
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="header" name="Content-Type" value="text/xml" />
<cfhttpparam type="xml" value="#trim( soapBody )#" />
</cfhttp>
<cfif find( "200", httpResponse.statusCode )>
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<cfset responseNodes = xmlSearch(soapResponse, "//*[ local-name() = 'VCfaultdetails'] ") />
<cfif arrayLen(responseNodes) NEQ 0>
<cfset error = #responseNodes[ 1 ].message.xmlText#>
<cfreturn error>
<cfelse>
<cfreturn "">
</cfif>
</cfif>
</cffunction>
</cfcomponent>
Code for the CFM version:
<cfsavecontent variable="soapBody">
<cfoutput>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ass="http://XXXXX">
<soapenv:Header/>
<soapenv:Body>
<ass:LogAgPreserveFiling>
<ass:AG.PRES.NR>#ag_pres_nr#</ass:AG.PRES.NR>
<ass:TC>04</ass:TC>
<ass:EMP.NR>#emp_nr#</ass:EMP.NR>
<ass:LCAQ.DT.RCVD>#dt_rcvd#</ass:LCAQ.DT.RCVD>
</ass:LogAgPreserveFiling>
</soapenv:Body>
</soapenv:Envelope>
</cfoutput>
</cfsavecontent>
<cfhttp url="XXXXXXXXXXXXX" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="XXXXXXXXXXXXXXX"/>
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="Authorization" value="Basic XXXXXXXXXXXXXXXXX" />
<cfhttpparam type="header" name="accept-encoding" value="no-compression" />
<cfhttpparam type="xml" value="#trim( soapBody )#" />
</cfhttp>
<cfif find( "200", httpResponse.statusCode )>
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<cfset responseNodes = xmlSearch( soapResponse, "//*[ local-name() = 'VCfaultdetails'] " ) />
<cfif arrayLen(responseNodes) NEQ 0>
<cfoutput>
Code: #responseNodes[ 1 ].errorcode#
<br />
Message: #responseNodes[ 1 ].message#
</cfoutput>
<cfelse>
Success!!!!!!!!
</cfif>
</cfif>
I XXXXXX out some of the URL's and such for security. Also, sorry for the namespace the developers choose (ass:). It was the abbreviation for Assessor. Somebody was being funny...

Facebook Graph API & ColdFusion: "Param no_story must be a boolean"

I'm trying to post an image to an album via the Facebook Graph API with following ColdFusion-Code:
<cfhttp method="post" url="https://graph.facebook.com/#albumid#/photos/">
<cfhttpparam type="formfield" name="access_token" value="#access_token#" />
<cfhttpparam type="file" name="source" file="#img_dir#\dummy.jpg" />
<cfhttpparam type="formfield" name="message" value="foo bar" />
<cfhttpparam type="formfield" name="no_story" value="true" />
</cfhttp>
If I omit no_story=true, the whole thing works perfectly, however I need this attribute to prevent the post from appearing on my wall. I'm getting this error:
{"error":{"message":"(#100) Param no_story must be a boolean","type":"OAuthException","code":100}}
HTTP/1.1 400 Bad Request Content-Type: text/javascript; charset=UTF-8 WWW-Authenticate: OAuth "Facebook Platform" "invalid_request" "(#100) Param no_story must be a boolean" Access-Control-Allow-Origin: * X-FB-Rev: 1568945 Pragma: no-cache Cache-Control: no-store Facebook-API-Version: v2.2 Expires: Sat, 01 Jan 2000 00:00:00 GMT X-FB-Debug: Vt7Viz/nlNfsQDDfNKtVuBjfgjDiWPFxYb0TAEpJJa9NjrR+TrEB8nuMOerQJYMX9E2e1CeqfBZT70/1KODErg== Date: Wed, 21 Jan 2015 12:13:31 GMT Connection: close Content-Length: 98
I have tried following variations:
<cfhttpparam type="formfield" name="no_story" value="TRUE" />
<cfhttpparam type="formfield" name="no_story" value="True" />
<cfhttpparam type="formfield" name="no_story" value="#true#" />
<cfhttpparam type="formfield" name="no_story" value="#JavaCast('boolean', true)#" />
<cfhttpparam type="formfield" name="no_story" value="1" />
<cfhttpparam type="formfield" name="no_story" value="Yes" />
None of these worked.
Difficult to test that out, but I suspect maybe it is passing the text as opposed to the boolean value. Maybe try:
<cfset mytruebool = True>
Then:
<cfhttpparam type="formfield" name="no_story" value="#mytruebool#" />
The key difference being no quotes on the cfset assignment.

How to pass parameter in Form Scope for REST services in ColdFusion?

Today while working with ColdFusion 10 REST, I got an issues. I am not sure how to pass data to a REST service in FORM scope.
Here is my REST enabled CFC,
<cfcomponent rest="true" restpath="/crudService" >
<cfset variable.myQuery = queryNew("Id,Name","Integer,Varchar",[[1,"Test1"],[2,"Test2"],[3,"Test3"]] )>
<cffunction name="getHandlerJSONForm" access="remote" httpmethod="GET" restpath="/formtest" returntype="query" produces="application/xml">
<cfargument name="customerID" required="true" restargsource="Form" type="numeric" >
<cfquery dbtype="query" name="local.qryGetUserName">
SELECT Name
FROM variable.myQuery
WHERE Id = <cfqueryparam cfsqltype="cf_sql_integer" value="#customerID#">
</cfquery>
<cfreturn local.qryGetUserName>
</cffunction>
</cfcomponent>
Here is the CFM code, calling the REST service,
<cfset restInitApplication("E:\Local Workspace\cfcs\rest","myfirstrest")>
<cfhttp url="http://cflocal.com/rest/myfirstrest/crudService/formtest" method="get" >
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" >
<cfhttpparam type="formfield" name="customerID" value="1" >
</cfhttp>
<cfdump var="#cfhttp#">
In StatusCode I am getting 500 Exception obtaining parameters ?
Please suggest whats going wrong here.

Making SOAP call using Perl's SOAP::Lite and a WSDL file

I want to make a SOAP call to a local web service. The web service is defined via a WSDL file (see below). I want to use Perl and SOAP::Lite. I tried this:
use strict ;
use warnings ;
use SOAP::Lite ;
my $endpoint = qq{http://example.com:2222/orawsv/PS_API/ACCOUNT_WS} ;
my $tns = 'http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS' ;
my $method_urn = $tns ;
my $soapaction = $tns ;
my $method = 'GET_BY_ACCOUNT_NUMBER' ;
my $sObj = SOAP::Lite->new(uri => $soapaction, proxy => $endpoint) ;
my $response = $sObj->call(SOAP::Data->name($method)->attr({ 'xmlns' => $method_urn})
=> SOAP::Data->name('ACCOUNT_NUMBER-VARCHAR2-IN' => '274724')) ;
print $response->faultstring() . "\n";
However, this results in an XML parsing failed error message. What would be the correct SOAP::Lite code to make this method call?
The HTTP request generated by the above is
Accept: text/xml
Accept: multipart/*
Accept: application/soap
Content-Length: 553
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS#GET_BY_ACCOUNT_NUMBER"
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GET_BY_ACCOUNT_NUMBER xmlns="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS">
<ACCOUNT_NUMBER-VARCHAR2-IN xsi:type="xsd:int">274724</ACCOUNT_NUMBER-VARCHAR2-IN>
</GET_BY_ACCOUNT_NUMBER>
</soap:Body>
</soap:Envelope>
Here is the WSDL file defining the web service:
<definitions name="ACCOUNT_WS"
targetNamespace="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema targetNamespace="http://xmlns.oracle.com/orawsv/PS_API/ACCOUNT_WS" elementFormDefault="qualified">
<xsd:element name="CACCOUNT_A-GET_BY_ACCOUNT_NUMBERInput">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ACCOUNT_NUMBER-VARCHAR2-IN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GET_BY_ACCOUNT_NUMBEROutput">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="RETURN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="GET_BY_ACCOUNT_NUMBERInputMessage">
<part name="parameters" element="tns:CACCOUNT_A-GET_BY_ACCOUNT_NUMBERInput"/>
</message>
<message name="GET_BY_ACCOUNT_NUMBEROutputMessage">
<part name="parameters" element="tns:GET_BY_ACCOUNT_NUMBEROutput"/>
</message>
<portType name="ACCOUNT_WSPortType">
<operation name="GET_BY_ACCOUNT_NUMBER">
<input message="tns:GET_BY_ACCOUNT_NUMBERInputMessage"/>
<output message="tns:GET_BY_ACCOUNT_NUMBEROutputMessage"/>
</operation>
</portType>
<binding name="ACCOUNT_WSBinding" type="tns:ACCOUNT_WSPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GET_BY_ACCOUNT_NUMBER">
<soap:operation soapAction="GET_BY_ACCOUNT_NUMBER"/>
<input>
<soap:body parts="parameters" use="literal"/>
</input>
<output>
<soap:body parts="parameters" use="literal"/>
</output>
</operation>
</binding>
<service name="ACCOUNT_WSService">
<documentation>Oracle Web Service</documentation>
<port name="ACCOUNT_WSPort" binding="tns:ACCOUNT_WSBinding">
<soap:address location="http://example.com:2222/orawsv/PS_API/ACCOUNT_WS"/>
</port>
</service>
</definitions>
Since you have the WSDL, you shouldn't have to construct SOAP::Data objects at all. Simply load the WSDL into your client object and call the method directly:
my $client = SOAP::WSDL->new(wsdl => $url_of_wsdl);
my $result = $client->$method(#arguments);
Yes, it's that easy!
Looks like this is about a year old, so this might not be relevant any longer. Anyway, based on the soap::lite documentation on CPAN it looks like you want to do this:
my $response = $sObj->call(SOAP::Data->name($method)->attr({ 'xmlns' => $method_urn}),
SOAP::Data->name('parameters')->value(SOAP::Data->value([
SOAP::Data->name('ACCOUNT_NUMBER-VARCHAR2-IN' => '274724'),
]))
);
die $response->fault->{ faultstring } if ($response->fault);
print $response->result, "\n";