I have a twitter application which sends tweets automatically for uses of our blog application whenever they post a new blog item.
This application is now returning an error
HTTP/1.1 401 Unauthorized Content-Type: application/json; charset=utf-8 Date: Mon, 12 Nov 2012 22:05:27 UTC Server: tfe
{"errors":[{"message":"Could not authenticate you","code":32}]}
My coldfusion code is as follows for posting the tweet:
<cfset var tweetURL = "https://api.twitter.com/1.1/statuses/update.json">
<cfhttp url="#tweetURL#" method="post" result="result">
<cfhttpparam type="header" name="Authorization" value="#oauth.header#" encoded="no">
<cfhttpparam type="formfield" name="status" value="#tweet#" encoded="no">
</cfhttp>
I have dumped out all the oauth header values, they are all as they should be, they are not returning any errors at all. its only the status update that is returning the unauthorized error.
What other things do I need to check? I thought my app may have been blocked or something but its all up and working. I've tested the user accounts they have authorized the app.
I worked it out. I was to busy validating the input of the header and auth tokens etc that I overlooked the status. It wasn't urlencoded. although this apparently worked in the old version. it didn't pass for the new.
Related
I'm trying to get the stripe api working with 'cfhttp' but not having much luck.
<cfhttp
url="https://api.stripe.com/Stripe/Stripe::setApiKey('MyLiveKeyHere');"
authType="Basic" name="StripeAPI" method="Post">
>
<cfoutput>#StripeAPI.statusCode#</cfoutput>
This gives me an error
Message
Invalid CSV line size, expected 1 columns but found 2 instead
Detail
[message: You did not provide an API key. You need to provide your API key in the Authorization header, using Bearer auth (e.g. 'Authorization: Bearer YOUR_SECRET_KEY').
I cant find anything online that is helping me - anyone got any ideas?
Thanks
Found out how to do it - through trial and error...
<cfhttp url="https://api.stripe.com/v1/customers/*CustID*" method="Get">
<cfhttpparam type="header" name="Authorization" value="Bearer *Live Key Here*">
</cfhttp>
To authenticate with the Stripe API, you need to use either basic auth or a bearer token rather than placing the API key in the url. For example, to list charges you could do something like this:
<cfhttp url="https://api.stripe.com/v1/charges" method="get" username="sk_test_xxxyyyz">
You'd then want to de-serialize the JSON response.
I have a question regarding sending a Web API call to sendgrid:
The following documentation is used to retrieve advanced stats:
http://sendgrid.com/docs/API_Reference/Web_API/Statistics/statistics_advanced.html
In the "Call" section, the following has been mentioned:
POST https://api.sendgrid.com/api/stats.getAdvanced.json
POST Data api_user=your_sendgrid_username&api_key=your_sendgrid_password&start_date=2013-01-01&end_date=2013-01-02&data_type=global
I understand that I need to use cfhttp for the Web API call and I should be
mentioning "https://api.sendgrid.com/api/stats.getAdvanced.json" in the url parameter
of the cfhttp tag.
Where do I need to mention api_user and api_key portion? I understand that I will have
to mention my sendgrid's account username and password here.
For Explanation Purpose let's consider the following dummy values for:
api_user = stack
api_key = 123456
Please let me know. I am trying to send an API call an get the data back in JSON format.
Thanks
ATTEMPT #1
I am using the following code:
<cfhttp url="https://api.sendgrid.com/api/stats.getAdvanced.json" method="POST" result="returnStruct">
<cfhttpparam name="api_user" value="stack" type="formfield">
<cfhttpparam name="api_key" value="123456" type="formfield">
<!--- <cfhttpparam name="days" value="5" type="formfield"> --->
<cfhttpparam name="start_date" value="2013-12-06" type="formfield">
<!--- <cfhttpparam name="end_date" value="2013-12-09" type="formfield"> --->
</cfhttp>
<cfdump var="#returnStruct#">
I am getting the following error in the form of Structure. Am I doing something wrong above? Please check my code below.
Charset [empty string]
ErrorDetail [empty string]
Filecontent {"error": "error in data_type: data_type is required"}
Header HTTP/1.1 400 Bad Request Content-Type: text/html Connection: close Date: Tue, 10 Dec 2013 06:21:19 GMT Server: nginx/1.4.2
Mimetype text/html
Responseheader
struct
Connection close
Content-Type text/html
Date Tue, 10 Dec 2013 06:21:19 GMT
Explanation Bad Request
Http_Version HTTP/1.1
Server nginx/1.4.2
Status_Code 400
Statuscode 400 Bad Request
Text YES
I am wondering, which data_type it is referring to, as the documentation doesn't talks about it.
Typically, you would use <cfhttpparam> for each of the keys:
<cfhttp url="https://api.sendgrid.com/api/stats.getAdvanced.json" method="POST">
<cfhttpparam name="api_user" value="some_username_goes_here" type="formfield">
<cfhttpparam name="api_key" value="some_api_key_goes_here" type="formfield">
...more params...
</cfhttp>
We are trying to interact with a RESTful web service that expects a file.
I set the name of the field to data (as required by the API) and then specify the file as an absolute path. When the file makes it to the server, the filename in the HTTP transaction is the complete absolute path.
This causes a problem with the API as the full path is then recorded as the "FileName".
How do I get ColdFusion to report only the file name rather than the full path?
We are using ColdFusion 9.
Here is the CFML:
<cfhttp url="http://server/testcode"
port="9876"
method="post"
result="Content">
<cfhttpparam type="file"
name="data"
file="c:\temp\testfile.txt">
</cfhttp>
Here are some examples of the HTTP interactions with different browsers:
CFHTTP 9
-------------------------------7d0d117230764
Content-Disposition: form-data; name="data"; filename="c:\temp\testfile.txt"
Content-Type: text/plain
This is the text, really long, well, not really.
-------------------------------7d0d117230764--
IE8
-----------------------------7db370d80e0a
Content-Disposition: form-data; name="FileField"; filename="C:\temp\testfile.txt"
Content-Type: text/plain
This is the text, really long, well, not really.
-----------------------------7db370d80e0a--
Chrome 13
------WebKitFormBoundaryDnpFVJwCsZkzTGDc
Content-Disposition: form-data; name="FileField"; filename="testfile.txt"
Content-Type: text/plain
This is the text, really long, well, not really.
Firefox 6
-----------------------------22798303036224
Content-Disposition: form-data; name="FileField"; filename="testfile.txt"
Content-Type: text/plain
This is the text, really long, well, not really.
-----------------------------22798303036224--
Apparently IE8 and CFHTTP both do the same thing (add "c:\temp" to the file name). I'm not sure what the spec for HTTP is, but it would be nice if there was a way to get CFHTTP to leave the path off.
Is there any way to do this?
I ran into a problem similar to yours, once. I didn't care about excluding the path, but I wanted to send a different filename than the name of the file on my server's filesystem. I could not find a way to do it using CF tags at all, but I was able to get it to work by dropping into Java. I used org.apache.commons.httpclient, which ships with CF9 IIRC. It goes something like this (pardon any typos, I'm transposing from more complicated code):
oach = 'org.apache.commons.httpclient';
oachmm = '#oach#.methods.multipart';
method = createObject('java', '#oach#.methods.PostMethod').init(post_uri);
filePart = createObject('java', '#oachmm#.FilePart').init(
'fieldname',
'filename',
createObject('java', 'java.io.File').init('filepath')
);
method.setRequestEntity(
createObject('java', '#oachmm#.MultipartRequestEntity').init(
[ filePart ],
method.getParams()
)
);
status = createObject('java', '#oach#.HttpClient').init().executeMethod(method);
method.releaseConnection();
I see that the content type is text/plain so first I think that you need to add the multipart property on the CFHTTP
<cfhttp url="http://server/testcode"
port="9876"
method="post"
result="Content"
multipart = "yes">
<cfhttpparam type="file"
name="data"
file="c:\temp\testfile.txt">
</cfhttp>
Could solve your issue.
The only difference I see between all of the posts is that CF is sending name="data" while everything else is sending name="FileField". If the other browser submissions are correct, then I would change your cfhttpparam:
<cfhttpparam type="file"
name="FileField"
file="c:\temp\testfile.txt">
or even try sending an additional FileName parameter:
<cfhttpparam type="file"
name="data"
file="c:\temp\testfile.txt" />
<cfhttpparam type="formField"
name="FileName"
value="testfile.txt" />
So I was able to get access to the API and made it work. Here is the code for this specific part (as I assume that you were able to login and get a document guid).
<!--- upload a document --->
<cfhttp method="post" url="<path to watchdox api upload>/#local.guid#/upload">
<cfhttpparam type="header" name="Content-type" value="multipart/form-data">
<cfhttpparam type="header" name="x-wdox-version" value="1.0">
<cfhttpparam type="header" name="x-wdox-ssid" value="#local.xwdoxssid#" >
<cfhttpparam type="formfield" name="filename" value="testfile.txt" >
<cfhttpparam type="file" file="c:\temp\testfile.txt" name="data" >
</cfhttp>
Hope it will help.
I'm trying to post an XML file to a multipart HTML form, it's not working, and I can't figure out what the problem is. It appears that ColdFusion is just not transmitting the file. I've tried posting to the actual form I need to post to as well as a test page that dumps requests, and all that comes through are the form fields.
Here's the relevant part of my code:
<cfhttp url="#endPoint#" method="post" multipart="yes">
<cfhttpparam type="formField" name="file_name" value="test.xml">
<cfhttpparam type="formField" name="user_name" value="test">
<cfhttpparam type="formField" name="password" value="test">
<cfhttpparam type="file" name="test.xml" file="#localfile#">
</cfhttp>
I can confirm that endPoint points to a valid URL, the formField names/values are valid, and that test.xml does indeed exist at the location specified by localfile.
Suggestions? Any input would be appreciated!
Add'l info: I am on CF MX 6.1 if that makes a difference.
EDIT: After reviewing the input below, I did some more testing.
I can confirm that localfile is an absolute path (C:\path_to_my_files\test.xml).
I'm not sure what the target form is running on. I don't know for sure, but I don't think it's ColdFusion.
I built my own HTTP test page using GetHTTPRequestData() as mentioned below, and I think that works ok, though it looks a litle strange to me. Writing GetHTTPRequestData().content to a file lets me see what I'm trying to send. However, the final form still reports that I'm not including a file. Posttestserver.com also reports no file. I've included the result from both my page and the POST test server below.
My test page result:
-------------------------------7d0d117230764
Content-Disposition: form-data; name="file_name"
Content-Type: text/plain; charset=UTF-8
test.xml
-------------------------------7d0d117230764
Content-Disposition: form-data; name="user_name"
Content-Type: text/plain; charset=UTF-8
test
-------------------------------7d0d117230764
Content-Disposition: form-data; name="password"
Content-Type: text/plain; charset=UTF-8
test
-------------------------------7d0d117230764
Content-Disposition: form-data; name="test.xml"; filename="C:\my_files\test.xml"
Content-Type: text/xml
%3C%3Fxml%20version%3D%221%2E0%22%20encoding%3D%22UTF%2D8%22%20%3F%3E%3CjobFeed%3E%3Cjob%3E%3CjobId%3E1234%3C%2FjobId%3E%3CjobTitle%3ETest%20Job%3C%2FjobTitle%3E%3CjobCity%3ETest%20City%3C%2FjobCity%3E%3CjobState%3ETest%20State%3C%2FjobState%3E%3CjobDescription%3ETest%20Description%3C%2FjobDescription%3E%3CjobZip%3E12345%3C%2FjobZip%3E%3CjobUrl%3Ehttp%3A%2F%2Fwww%2Etest%2Ecom%3C%2FjobUrl%3E%3CJobType%3ETEC%3C%2FJobType%3E%3C%2Fjob%3E%3C%2FjobFeed%3E
-------------------------------7d0d117230764--
I've got no idea what this "-------------------------------7d0d117230764" business is.
Here's what I got from the test site:
Headers (Some may be inserted by server)
UNIQUE_ID = TlZTra3sqvkAAECsSBsAAAAL
HTTP_HOST = www.posttestserver.com
HTTP_CONNECTION = close
HTTP_USER_AGENT = ColdFusion
HTTP_ACCEPT_ENCODING = deflate, gzip, x-gzip, compress, x-compress
CONTENT_TYPE = multipart/form-data; boundary=-----------------------------7d0d117230764
CONTENT_LENGTH = 1159
GATEWAY_INTERFACE = CGI/1.1
REQUEST_METHOD = POST
QUERY_STRING =
REQUEST_URI = /post.php
REQUEST_TIME = 1314280365
Post Params:
key: 'file_name' value: 'test.xml'
key: 'user_name' value: 'test'
key: 'password' value: 'test'
== Begin post body ==
== End post body ==
Here it appears I've transmitted no file.
I'm still looking at it, but I'm not seeing the problem. Ideas?
When you specify a type of file, then the file data is sent in the post body, not in a form field name that you can reference. If you check the LiveDocs on CFHTTPPARAM it states for the type="file" attribute:
The absolute path to the file that is sent in the request body.
So as Leigh stated, on your receiving page, you need to use GetHttpRequestData, something like this:
<cfset objRequest = GetHttpRequestData() />
<cfset object = objRequest.Content() />
If the endPoint is a CF page, then I am wondering if something else may be going on. The data is sent in the request body, yes. But with CF pages, it should still parse the information and create a form field for that file. Same as with a regular form upload. In this case the field name would be form["test.xml"]. Could that be part of the issue?
CFDUMP results under MX6.1 and CF9
FIELDNAMES FILE_NAME,USER_NAME,PASSWORD,TEXT.XML
FILE_NAME test.xml
PASSWORD test
TEXT.XML C:\CFusionMX\...\temp\wwwroot-tmp\neotmp6275345679234991.tmp
USER_NAME test
Note: One difference under CF9 was that getHttpRequestData().content is empty. Whereas under MX6 it is still populated. Seems like 6.1 preserves a copy of the data (after processing it) but CF9 does not. Not sure why.
I'm searching for a way to create a new CouchDB user without using Futon or Curl... just a straight http request.
One way I found (http://stackoverflow.com/questions/3456256/error-creating-user-in-couchdb-1-0) puts a JSON doc to "http://localhost:5984/_users/org.couchdb.user:username" to create a user.
I have attempted the following:
<cfhttp url="http://127.0.0.1/_users/org.couchdb.user:xyz_company" port="5984" method="PUT" username="#variables.couch_username#" password="#variables.couch_password#">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type='body' name='org.couchdb.user:xyz_company' value='{"roles":[],"name":"xyz_company","salt":"3B33BF09-26B9-D60A-8F469D01286E9590","id":"org.couchdb.user:xyz_company","password_sha":"096EA41A5A81EA1507F2C6F7EDC364C0B82694AC","type":"user"}'>
I keep receiving the following back from Couch:
cfhttp.statuscode = 405 Method Not Allowed
cfhttp.filecontent = Method Not Allowed; The requested method PUT is not allowed for the URL /_users/org.couchdb.user:xyz_company
Any thoughts or suggestions?
UPDATE:
I edited my code based on Marcello's suggestions. I still receive the same 405 Method Not Allowed error. Here is the code now:
<cfhttp url="http://127.0.0.1/_users/org.couchdb.user:xyz_company" port="5984" method="PUT" username="#variables.couch_username#" password="#variables.couch_password#"><cfhttpparam type="header" name="Content-Type" value="application/json;charset=UTF-8"><cfhttpparam type='body' value='{"roles":[],"name":"xyz_company","salt":"3B33BF09-26B9-D60A-8F469D01286E9590","_id":"org.couchdb.user:xyz_company","password_sha":"096EA41A5A81EA1507F2C6F7EDC364C0B82694AC","type":"user"}'></cfhttp>
Any more suggestions? Thank you!
curl is a straight http request. There are other ways to create such requests: you can craft them with your browser; you can use a different program (e.g. wget); or even write your own (e.g. in Python or in JavaScript with V8 or Rhino).