CFHTTP & CloudFlare API: DELETE purge_everything not working - coldfusion

Has anyone else been able to DELETE purge_everything with CFHTTP?
I can't seem to get ColdFusion CFHTTP to successfully purge a CloudFlare zone's cache. But I am able to do other things like list zones, etc. So I know I can successfully CFHTTP to CloudFlare's API.
This is the curl command, which works:
curl -svX DELETE -H 'X-Auth-Email: a#b.c' -H 'X-Auth-Key: XYZ' https://api.cloudflare.com/client/v4/zones/xxxxxxx/purge_cache -H 'Content-Type: application/json' --data '{"purge_everything":true}'
The error returned is:
{"success":false,"errors":[{"code":1012,"message":"Request must
contain one of \"purge_everything\" or \"files\", or
\"tags"}],"messages":[],"result":null}
I've tried so many combinations of code... these are the different variables I've tried:
<cfset stFields = '{"purge_everything":true}'>
<cfset stFieldsJson = {"purge_everything":true}>
<cfset stFieldsJson2 = {
"fields" : {
"purge_everything" : true
}
}>
<cfset stFieldsJson3 = {
"purge_everything" : true,
"fields" : {
"purge_everything" : true
}
}>
<cfset tmp = {} />
<cfset tmp['purge_everything'] = true />
... and here are some different combinations of calls I've made...
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare" charset="utf-8">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value="#serializeJson(stFieldsJson)#" encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare" charset="utf-8">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value="#serializeJson(stFieldsJson2)#" encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value="#serializeJson(stFieldsJson3)#" encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value="#serializeJson(tmp)#" encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare" charset="utf-8">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value='{"purge_everything":true}' encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare" charset="utf-8">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value='"purge_everything":true' encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
<cfhttp url="https://api.cloudflare.com/client/v4/zones/4da78b2707f9753eb79a93d505b4d0d3/purge_cache" method="DELETE" result="cFlare" charset="utf-8">
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value='purge_everything' encoded="false">
</cfhttp>
<cfdump var="#cFlare#"><Cfflush>
I've also tried with and without the 'Encoded' Body attribute, with and without the 'Charset' attribute in all places.
Any help is appreciated.

Not sure which version of CF you are running. However, I suspect you are not doing anything wrong, but that <cfhttp> simply is not sending a body when the method="DELETE", which would make sense given the error message.
A simple way to test it is point your <cfhttp> call to a test page on your local CF server. On the test page dump GetHttpRequestData() so you can view the actual headers and content submitted. (Another option is to use the built in TCPMonitor on an open port, which provides more detail about both request and response. However, for this scenario, the first method is simplest.)
Test Page
<!--- echo request headers and content --->
<cfdump var="#getHTTPRequestData()#">
Request
<!--- simulate request --->
<cfset requestBody["purge_everything"] = true>
<cfhttp url="http://localhost/testPage.cfm" method="DELETE" result="cFlare" charset="utf-8" >
<cfhttpparam type="header" name="X-Auth-Email" value="a#b.c">
<cfhttpparam type="header" name="X-Auth-Key" value="XYZ">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=utf-8">
<cfhttpparam type="header" name="accept" value="*/*">
<cfhttpparam type="body" value="#serializeJson(requestBody)#" encoded="false">
</cfhttp>
<!--- display request headers and content --->
<cfoutput>#cFlare.fileContent#</cfoutput>
Notice the content, or body, is empty when method="DELETE"? However, change it to method="POST" and the content magically appears.
Sending a body with a DELETE request should be valid, so it sounds like a bug. If so, you will need to find a different tool to make the http request, such as invoking curl.exe from cfexecute, or using a custom tag like cfx_http5, or use java classes like as URLConnection or Apache's HTTPClient.

After reading up on some docs, it appears that the CloudFlare API is mixing methods in a way that CFHTTP will not.
CloudFlare's API states to use the DELETE method and content type header of "application/json". Their exact example is:
$ curl -X DELETE "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/purge_cache" \
-H "X-Auth-Email: user#example.com" \
-H "X-Auth-Key: c2547eb745079dac9320b638f5e225cf483cc5cfdda41" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'
However when one uses --data, curl will POST with content-type application/x-www-form-urlencoded. https://curl.haxx.se/docs/manpage.html#-d
CFHTTP however is following specs.
POST is used to send data. DELETE is for deleting the URI.
POST: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5
DELETE: https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7
When I CFHTTP with POST I get an error that only DELETE is accepted for the URI. When I CFHTTP with DELETE, no content is being POSTed.
My workaround, without going out of standard CFML, was to use their v1 API. It's working like a champ. https://www.cloudflare.com/docs/client-api.html

Related

Coldfusion How to save PDF Response Stream to File

We have a REST API that returns a stream of content-type application/pdf. I just want to save it to a file on the server.
<cfhttp url="#ApiPath#" method="post" result="res">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#payload#" />
</cfhttp>
<cffile action = "write" file = "#FileName#" output = "#res.fileContent#">
I've producing a blank PDF, any ideas? ( ive tried various combinations of cfdocument/cfpdf with no luck)
here's a dump of the REST response:
I think I've got it:
Solution 1:
<cfhttp url="#url#" method="post" result="res">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#payload#" />
</cfhttp>
<cfset bytes = res.FileContent.toByteArray()>
<cfscript>
fos = createObject("java", "java.io.FileOutputStream").init("myfile.pdf");
fos.write(bytes);
fos.flush();
fos.close();
</cfscript>
EDIT: Based on SOS's solution this also worked:
Solution 2:
<cfhttp url="#url#" method="post" result="res" getAsBinary="Auto">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#payload#" />
</cfhttp>
<cfset fileName = listlast(res["responseHeader"]["content-disposition"],";=")>
<cffile action="write" file="#path#\#fileName#" output="#res.FileContent#">

Export to Excel in ColdFusion

I am posting few inputs into a url using cfhttp and expecting to download some data in a xls file. I am trying to do get data using cffile ="write" which doesn't work. Can any one suggest how can we go with this. Here is the code below
<cfhttp url="#Baseurl#" method="post" result="ExportToExcelresult" redirect="no" resolveurl="true">
<cfhttpparam type="header" name="REFERER" value="#Baseurl#" >
<cfhttpparam type="header" name="Cache-Control" value="no-cache">
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded">
<cfhttpparam type="header" name="Connection" value="keep-alive" >
<cfhttpparam type="header" name="User-Agent" value="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36">
<cfhttpparam type="header" name="cookie" value="TestCookie=;" encoded="yes">
<cfloop collection="#CookieList#" item="i">
<cfhttpparam type="header" name="cookie" value="#CookieList[i]#" encoded="yes">
</cfloop>
<cfloop collection="#PostCookieList#" item="i">
<cfhttpparam type="header" name="cookie" value="#PostCookieList[i]#" encoded="yes">
</cfloop>
<cfloop collection="#PostDefaultCookieList#" item="i">
<cfhttpparam type="header" name="cookie" value="#PostDefaultCookieList[i]#" encoded="yes">
</cfloop>
<cfhttpparam name="ToolkitScriptManager1_HiddenField" value="" type="formfield">
<cfhttpparam name="LeftNav1_LoginView1_treeView1_ExpandState" value="#EXPANDSTATE#" type="formfield">
<cfhttpparam name="LeftNav1_LoginView1_treeView1_SelectedNode" value="#SELECTNODE#" type="formfield">
<cfhttpparam name="__EVENTTARGET" value="" type="formfield">
<cfhttpparam name="__EVENTARGUMENT" value="" type="formfield">
<cfhttpparam name="LeftNav1_LoginView1_treeView1_PopulateLog" value="" type="formfield">
<cfhttpparam name="__VIEWSTATE" value="#VIEWSTATE#" type="formfield">
<cfhttpparam name="__VIEWSTATEGENERATOR" value="#VIEWSTATEGENERATOR#" type="formfield">
<cfhttpparam name="__EVENTVALIDATION" value="#EVENTVALIDATION#" type="formfield">
<cfhttpparam name="ctl00$MainContent$repMUData$ctl00$btnExport" value="Export to Excel" type="formfield">
</cfhttp>
When I do cfdump here is the the result
When I do cfdump that it is giving some binary data. For sure I am getting some data but not sure how to extract the data into xls file
To write the binary data to file just use the function filewrite. In the following snippet I write to a temporary file, but you would write to were you want to permanently store the file. I then read file back into spreadsheet object to verify that the write worked as intended.
<cfhttp url="http://example.com/test.cfm" result="ExportToExcelresult">
</cfhttp>
<cfscript>
//Replace with the file path where you want to permanently store the file
yourFileLocation = getTempFile(getTempDirectory() ,"xls");
//Save to file system
filewrite(yourFileLocation, ExportToExcelresult.filecontent.toByteArray());
//Not needed. Only verifying there is a spreadsheet written to the file location
writeOutput("Is spreadsheet: " & isSpreadsheetFile(yourFileLocation));
//You will not be working with a temp file. Do not delete it.
fileDelete(yourFileLocation);
</cfscript>

cfhttp to the stats.ezhostingserver website not working

I have the following Updated code where I am trying to connect to the website using the username/password and siteid combination, i am passing all values using get method and trying to fetch cookie to authenticate and go ahead but somehow i am again getting redirected to the login screen
My Code
<cfhttp method="get" url="https://stats.ezhostingserver.com/Login.aspx" resolveurl="true" redirect="false">
<cfhttpparam type="URL" name="ctl00$MPH$txtUserName" value="********">
<cfhttpparam type="URL" name="ctl00$MPH$txtPassword" value="********">
<cfhttpparam type="URL" name="ctl00$MPH$txtSiteId" value="*****">
<cfhttpparam type="Header" name="Accept-Encoding" value="deflate;q=0">
<cfhttpparam type="Header" name="TE" value="deflate;q=0">
</cfhttp>
<cfset stm_cookies = cfhttp.responseHeader['Set-Cookie'] />
<cfset stm_temp = REReplace(stm_cookies, ";.*", "")>
<cfset stm_cookieName = listfirst(stm_temp,'=')>
<cfset stm_cookievalue = listlast(stm_temp,'=')>
<cfhttp method="get" url="https://stats.ezhostingserver.com/default.aspx" charset="utf-8" result="results" redirect="no">
<cfhttpparam type="cookie" name="#stm_cookieName#" value="#stm_cookievalue#">
</cfhttp>
<cfoutput>#results.filecontent#</cfoutput>
But it is saying me object moved error

Push value to DucksBoard in ColdFusion

I going to implement the DucksBoard API. I made my custom counter on Ducksboard now I want to PUSH value. I read the tutorial I just found this line on DUCKSBOARD to push data
curl -v -u YOUR_API_KEY:unused -d '{"value": 10}' https://push.ducksboard.com/values/235
SO i try something like this in my Coldfusion code
<cfset var1 = '{"value":5}'>
<cfhttp url="https://push.ducksboard.com/values/xxxx" method="post" result="httpResp" timeout="60">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#serializeJSON(var1)#">
</cfhttp>
There is less information in the site of Duckboard.Can someone has implemented this.If yes then kindly tell me how to push value and where to use my API key?
I've not used Duckboard but it looks like what you have is correct. The CFHTTP tag takes 2 more parameters, username and password which you can fill in with your username and your API password like so:
<cfset var1 = '{"value":5}'>
<cfhttp url="https://push.ducksboard.com/values/xxxx" method="post"
result="httpResp" timeout="60" username="myusername" password="mypassword"
>
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#serializeJSON(var1)#">
</cfhttp>
I study the API and found the solution You can use this code and change with yours this will work.And don't use serializeJSON in body tag.
<cfset var1 = '{"value":5}'>
<cfhttp url="https://push.ducksboard.com/v/xxxx" method="post" username="API-key" password="x" result="httpResp" >
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value='#var1#'>
</cfhttp>

ColdFusion CFHTTP GET strips cookie

I'm running into issues trying to pass a cookie in my CFHTTP GET Statement.
Has anyone else experienced this? Pointers would be appreciated. BTW - I am using the x-http-method-override, because I saw this on a few other sites that were discussing this topic.
<cfhttp url="#this.apiServer#/api/v#this.version#/user.json"
method="POST" result="jorn">
<cfhttpparam type="COOKIE" name="ms_user" value="#arguments.patAppSession#" />
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="header" name="x-http-method-override" value="GET" />
<cfhttpparam type="body" value='#variables.dataFields#' />
</cfhttp>
<cfdump var = "#jorn#">