views:

31

answers:

3

Hello, I'm having troubles with building correct PUT request to the Wufoo.

In all my attempts I see the same error:

404 A WebHook must contain a url parameter.

Here is the version with JSON data type:

<cfset local.action = "forms/#local.formHash#/webhooks.json" />

<cfset local.request = {"url" : local.webHookURL, "handshakeKey" : local.webHookKey} />

<cfset local.request["handshakeKey"] = local.webHookKey />

<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
    <cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8" />
    <cfhttpparam type="body" value="#SerializeJSON(local.request)#" />
</cfhttp>

Same failure when using file:

<cfset local.action = "forms/#local.formHash#/webhooks.json" />

<cfset local.request = {"url" : local.webHookURL, "handshakeKey" : local.webHookKey} />

<cffile action="write" file="#GetTempDirectory()#webhook.json" output="#SerializeJSON(local.request)#">

<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
    <cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8" />
    <cfhttpparam type="file" mimetype="application/json" name="json" file="#GetTempDirectory()#webhook.json" />
</cfhttp>

UPDATE:

To make the code working in ACF (my code works in Railo only) use this syntax for request:

<cfset local.request = {} />
<cfset local.request["url"] = local.webHookURL />
<cfset local.request["handshakeKey"] = local.webHookKey />

Both methods should produce same JSON with case-sensitive keys.


Also I've tried the XML data type:

<cfset local.action = "forms/#local.formHash#/webhooks.xml" />

<cfsavecontent variable="putXML">
<cfoutput>
<?xml version="1.0" encoding="UTF-8"?>
<WebHookPutRequest>
<url>#XMLFormat(local.webHookURL)#</url>
<handshakeKey>#XMLFormat(local.webHookKey)#</handshakeKey>
</WebHookPutRequest>
</cfoutput>
</cfsavecontent>

<cffile action="write" file="#GetTempDirectory()#webhook.xml" output="#Trim(putXML)#">

<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
    <cfhttpparam type="header" name="Content-Type" value="application/xml; charset=UTF-8" />
    <cfhttpparam type="body" value="#putXML#" />
</cfhttp>

Here I'm not sure if my XML is correct, though for JSON everything should be fine.

Any ideas what's wrong with my code?

Thanks in advance.

A: 

In ColdFusion, generally, variable names are case-insensitive and uppercase.

<cfset local.request = {
  url = local.webHookURL,
  handshakeKey = local.webHookKey
} />

This gives you a struct with keys URL and HANDSHAKEKEY.

On the Web, presumably including with the Wufoo REST API, keys are case-sensitive. In this case, Wufoo accepts keys url, handshakeKey, and metadata - in that casing.

In ColdFusion, associative-array notation with struct puts (assignments) lets you keep the precise casing you want.

<cfset local.request = { } />
<cfset local.request["url"] = local.webHookURL />
<cfset local.request["handshakeKey"] = local.webHookKey />

This gives you a struct with keys url and handshakeKey.

Justice
This advice does not really applicable here. Please see updated posting -- notes about Railo vs ACF.
Sergii
A: 

Not familiar with this api but should the url, handshakekey, etc be form post params?

The following parameters must be passed as post parameters to the Web Hook API

url - this required parameter represents the URL on your server that the Web Hook will call when a new entry is submitted. We do validate the URL and reject malformed URLs.

handshakeKey - this optional parameter is described in the Web Hook integration getting started documentation.

metadata=true - this optional value parameter the Web Hook to send along form/field

The way I read that, it looks like they are asking for each of the params.

The error is suggesting it can't find the URL param, maybe that is it.

Joshua Cyr
It does not work either when using `<cfhttpparam type="url"` or `<cfhttpparam type="formfield"`. Not sure if this is applicable for PUT at all.
Sergii
+2  A: 

Wufoo asks for the parameters to be "be passed as post parameters to the Web Hook API". Try using the application/x-www-form-urlencoded encoding for the body of the request. In ColdFusion, you can do this with <cfhttpparam type="FormField" />.

<cfhttpparam type="FormField" name="url" value="#local.webHookURL#" />
<cfhttpparam type="FormField" name="handshakeKey" value="#local.webHookKey#" />

However, ColdFusion rejects this technique with PUT methods. You can encode the body yourself using:

<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded; charset=UTF-8" />
<cfhttpparam type="body" value="url=#UrlEncode(local.webHookURL)#&handshakeKey=#UrlEncode(local.webHookKey)#" />
Justice
Second advice worked! Thanks a lot, Justice!
Sergii
Related question: how would I send the `hash` attribute with `DELETE` reqest? `body` type does not work for DELETE, can't get `formField` working too. See this doc http://wufoo.com/docs/api/v3/webhooks/delete/
Sergii
ColdFusion understands `type="FormField"` only for `POST` requests. It is acceptable to include bodies in `DELETE` requests just as in `PUT` requests (see http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request), but you will have to use the same technique to include the body as you do for including bodies in a `PUT` request. If you need bodies of type `application/x-www-form-urlencoded`, then you should (in ColdFusion) use the technique described in this answer.
Justice
Filed as bug for you: http://cfbugs.adobe.com/cfbugreport/flexbugui/cfbugtracker/main.html#bugId=84729 vote it up!
Henry
@Sergii I re-read your last comment ... maybe there's nothing you can do directly in CF. Try using a Java library directly? http://hc.apache.org/httpclient-3.x/ was the first Google result.
Justice
@Justice, I've talked to the Wufoo developers and they agreed that they should not require any fields passing to the `DELETE` request because it has all needed into (form and webhook hashes) included into the URL. So now it is fixed and works perfectly with `cfhttp`. Thanks for help!
Sergii
Excellent! Cheers!
Justice