I'm trying to set up a REST Web Services with ColdFusion 10, and if I have an onError handler in Application.cfc to handle incorrect parameter error.
My Download API Service:
<cfcomponent rest="true" restpath="downloadStuff">
<cffunction name="downloadStuff" access="remote" returntype="String" httpmethod="GET">
<!--- parameters --->
<cfargument name="id" required="true" type="string" restargsource="query"/>
<cfargument name="account" required="true" type="string" restargsource="query"/>
<!--- download stuff logic --->
...
<cfreturn response>
</cffunction>
</cfcomponent>
It is expecting 2 parameters and user get a 500 error if parameters are not there. I don't want user to see the 500 error, I want user to see a normal response message asking user to add the missing parameter.
This is my onError handler in application.cfc
<cffunction name="onError" returntype="String" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<!--- error logging here --->
<cfset response = "Please add missing parameters">
<cfreturn response>
When user enter incorrect parameters to API, I am getting 500 error with "cannot convert the value "Please add missing parameters" to a boolean".
How can I pass back a response message in onError? Is there a better way to handle incorrect parameters error and return a message to user?
Can you please help me? I am trying to consume response in my ColdFusion application. Just wanted to try with this fake API before proceeding to the actual one.
I have created a component with two functions inside it. My cfc looks like this:
photoUploadNew.cfc
<cfcomponent displayname="test" hint="testing.." output="yes">
<cfsetting enablecfoutputonly="true" showdebugoutput="true">
<cffunction name="start" access="public" output="no" returntype="any" description="initialize the component">
<cfset variables.testUrl = "https://jsonplaceholder.typicode.com/posts">
<cfreturn this>
</cffunction>
<cffunction access="public" output="false" name="testGetReq" displayname="TestGetReq" description="testing" returntype="any">
<cfset variables.testUrl = "https://jsonplaceholder.typicode.com/posts">
<cfhttp
result="httpResponsetest"
url="#variables.testUrl#"
timeout="30"
method="get"
>
<cfhttpparam
type="header"
name="Content-Type"
value="application/json"
/>
</cfhttp>
</cfhttp>
<cfreturn httpResponsetest>
</cffunction>
</cfcomponent>
In my cfm page. I am trying to instantiate this component and print whatever I am getting as a response but I am not able to print anything out there.
<cfset testObj = CreateObject("component","usedGear_admin.cfc.photoUploadNew").testGetReq()>
<cfoutput >
#testObj#
</cfoutput>
Any help would be greatly appreciated.
I think you are using cfhttp result wrong here. When we do a cfhttp call,
<cfhttp
method="get"
result="httpResponsetest"
url="https://jsonplaceholder.typicode.com/posts"
timeout="30"
>
</cfhttp>
They try the following, you will see httpResponsetest has multiple keys. The data provided by API will be present in httpResponsetest.fileContent. Also most of the time there is Mimetype,Responseheader,Statuscode etc.
<cfdump var="#httpResponsetest.fileContent#">
Here you can see the data is in JSON format. That means you'll need to deserialize them to be able to use it.
<cfdump var="#deserializeJSON(httpResponsetest.fileContent)#">
You can deserialize it and return from the function. Along with that you'll need to handle the case where API responds with am error.
Demo
I've created a taffy API endpoint in patch verb
I would run the explore to throw the below error
Patch verb working stable in ACF but not working in lucee
MY lucee version -> Lucee 4.5.4.017 final
Any one let me know how to fix that issue
Mycode:
<cfcomponent extends="taffy.core.resource" taffy_uri="/artist/">
<cfset variables.dummyData = StructNew() />
<cfset variables.dummyData.whatever = true />
<cfset variables.dummyData.phone = encode.string(5558675309) />
<cfset variables.dummyData.phoneNumeric = 5558675309 />
<cffunction name="patch" access="public" output="false">
<cfreturn representationOf(variables.dummyData).withStatus(200) />
</cffunction>
</cfcomponent>
This is my error message:
ColdFusion could not delete the file
C:\path\guid.png
for an unknown reason.
I've already checked to make sure my coldFusion user has permission to do so, as suggested here. That is not the problem, the user has all the permissions. Unfortunately, the code is breaking on production servers, and not my own local server (could be relevant). Production is on CF11 but I am on CF9.
Here is the code:
<cffunction name="svgToPDF" access="public" output="false" returntype="string">
<cfargument name="svg" required="true" type="string" />
<cfset var local = {} />
<cfset local.guid = CreateUUID() />
<cfset local.outPDF = ExpandPath(local.guid & '.pdf') />
<cfset local.svg = DeserializeJSON(exportToImage(svg=arguments.svg)) />
<cfif local.svg.error>
<!-- Conversion error -->
<cfset FileDelete(#local.svg.file#) />
<cfreturn '' />
</cfif>
<!--- rotate the png --->
<cfimage
action="read"
source="#local.svg.file#"
name="local.objImage" />
<cfimage
action="rotate"
source="#local.objImage#"
angle="90"
name="local.objImage" />
<cfimage
action="write"
source="#local.objImage#"
destination="#local.svg.file#"
overwrite="yes" />
<!--- Add the png to the pdf, write the pdf file, and delete the png --->
<cfscript>
img = CreateObject("java", "com.lowagie.text.Image");
png = img.getInstance(local.svg.file);
document = CreateObject("java", "com.lowagie.text.Document");
document.init(png);
fileIO = CreateObject("java", "java.io.FileOutputStream");
fileIO.init(local.outPDF);
writer = CreateObject("java", "com.lowagie.text.pdf.PdfWriter");
writer.getInstance(document, fileIO);
document.setMargins(0, 0, 0, 0);
document.open();
document.add(png);
document.close();
FileDelete(#local.svg.file#); <!--- This is the line where it breaks--->
</cfscript>
<cfreturn local.outPDF />
</cffunction>
How can I fix this function?
Thanks
If you production server is CF11 then this is a bug that has been mentioned here, in Bug# 4031026 - http://bugbase.adobe.com/index.cfm?event=bug&id=4031026
The bug has been verified by Adobe and fix will be due, most probably in their next hotfix.
JPEG seems to be the only format that works at the moment without locking issues.
We have been struggling on an upgrade from Windows 2003 Server (ColdFusion 8) to Windows 2008 with ColdFusion 10. We finally have the settings correct to handle and process all of our ColdFusion code, with custom error handlers, and SSL functioning as expected.
However, when we started to have some users test different applications, we found out that no Domain Users can log in to the website, unless they are part of the Local Machine's Administrators group. We have another Windows 2008 Server running .NET and authenticating users correctly. I thoroughly compared the settings and they are the same.
This is how it is setup:
ColdFusion Services: all services (5) are running under the Local System, with the exception of the ColdFusion Application Server, which is running under a domain account.
IIS: We have 1 active website (Main Website) running on it's own Application Pool Integrated .NET 4.0, running as LocalSystem.
Authentication: Anonymous works, Anonymous account MUST be Application Pool Identity or else it won’t display anything. Basic Authentication is configured, and the default domain is configured.
Any and all help is appreciated as we have been working on this for months and thought the migration was ready to go. No one on my team is an expert at the installation of ColdFusion or IIS 7.5.
After much ado, I found the answer here: What are the proper permissions for ColdFusion 9 on IIS 7.5 with Windows Authentication
I needed to give the domain users (which is just a very large A/D group) read-only access to the config folder under the CF10 install location. From then on, it worked great!
If you're interested in a fairly robust solution as well, here's an example component (CFC) you could call, which also scrubs out possible injection characters. We've evolved this over the years for authentication so it is fairly battle tested.
<cfcomponent output="false">
<cffunction access="public" name="init" output="FALSE" returntype="any" hint="This is the pseudo constructor that allows us to play little object games." >
<cfset variables.ldapserver = application.yoursiteLDAP.server />
<cfset variables.ldapuser = application.yoursiteLDAP.user />
<cfset variables.ldappassword = application.yoursiteLDAP.password />
<cfset variables.ldaptimeout = application.yoursiteLDAP.timeout />
<cfset variables.ldapsecuremode = application.yoursiteLDAP.securemode />
<cfset variables.port = application.yoursiteLDAP.port />
<cfreturn This />
</cffunction>
<cffunction name="authenticate" access="public" output="false" returntype="struct" hint="">
<cfargument name="username" type="string">
<cfargument name="password" type="string">
<cfset var returnData = StructNew() />
<cfset var queryResult = QueryNew('') />
<cfset var userInfo = "" />
<cfset arguments.username = scrubStringforLDAPQuery(arguments.username) />
<cfset userInfo = retrieveUserInfo(arguments.username) />
<cfset returnData["authenticated"] = false />
<cfset returnData["detail"] = "" />
<cfset returnData["user_info"] = QueryNew("") />
<cftry>
<cfldap
action="query"
server="#variables.ldapserver#"
username="#userInfo.DN#"
password="#arguments.password#"
filter="(&(uid=#arguments.username#)(objectClass=account))"
name="queryResult"
attributes="cn,dn,uid,displayName,objectClass,uidNumber"
start="dc=yoursite,dc=subdomain,dc=domain,dc=com"
maxrows="1"
port="#variables.port#"
timeout="#variables.ldaptimeout#"
secure="#variables.ldapsecuremode#" />
<cfset returnData["authenticated"] = queryResult.RecordCount EQ 1 />
<cfset returnData["user_info"] = queryResult />
<cfcatch>
<cfif FindNoCase("Invalid Credentials",cfcatch.Message) LTE 0>
<cfrethrow />
</cfif>
<cfset returnData["detail"] = cfcatch.Message />
</cfcatch>
</cftry>
<cfreturn returnData />
</cffunction>
<cffunction name="retrieveUserInfo" access="public" output="false" returntype="query" hint="">
<cfargument name="username" type="string">
<cfset var queryResult = QueryNew('') />
<cfset arguments.username = scrubStringforLDAPQuery(arguments.username) />
<cfldap
action="query"
server="#variables.ldapserver#"
username="#variables.ldapuser#"
password="#variables.ldappassword#"
filter="(&(uid=#arguments.username#)(objectClass=account))"
name="queryResult"
attributes="cn,dn,uid,displayName,objectClass,uidNumber,shadowExpire,gecos,homeDirectory,loginShell"
start="dc=yoursite,dc=subdomain,dc=domain,dc=com"
maxrows="10"
port="#variables.port#"
timeout="#variables.ldaptimeout#"
secure="#variables.ldapsecuremode#" />
<cfif queryResult.RecordCount GT 1>
<cfthrow message="More than 1 user found in LDAP" detail="More than 1 user matched uid=#arguments.username#" />
</cfif>
<cfreturn queryResult />
</cffunction>
<cffunction name="retrieveGroupInfo" access="public" output="false" returntype="query" hint="">
<cfargument name="groupname" type="string">
<cfset var queryResult = QueryNew('') />
<cfset arguments.groupname = scrubStringforLDAPQuery(arguments.groupname) />
<cfldap
action="query"
server="#variables.ldapserver#"
username="#variables.ldapuser#"
password="#variables.ldappassword#"
filter="(&(cn=#arguments.groupname#)(objectClass=posixGroup))"
name="queryResult"
attributes="cn,dn,objectClass"
start="dc=yoursite,dc=subdomain,dc=domain,dc=com"
maxrows="10"
port="#variables.port#"
timeout="#variables.ldaptimeout#"
secure="#variables.ldapsecuremode#" />
<cfif queryResult.RecordCount GT 1>
<cfthrow message="More than 1 group found in LDAP" detail="More than 1 group matched uid=#arguments.groupname#" />
</cfif>
<cfreturn queryResult />
</cffunction>
<cffunction name="scrubStringforLDAPQuery" access="public" output="false" returntype="string" hint="Removes offensive characters from string for use in an LDAP query">
<cfargument name="stringToScrub" type="string">
<cfargument name="blockWildcard" type="boolean" default="false">
<cfset replaceCharacterList = ";=" />
<cfif arguments.blockWildcard>
<cfset replaceCharacterList &= "*" />
</cfif>
<cfset arguments.stringToScrub = REReplace(arguments.stringToScrub,"[#replaceCharacterList#]","","all") />
<cfreturn arguments.stringToScrub />
</cffunction>
</cfcomponent>