Ada*_*tle 5 php twitter coldfusion cfml
我正在使用一个不错的Twitter API包装器:codebird-js ; 并且它包含一个代理,如果您需要发出CORS AJAX请求(我这样做),因为Twitter的API不允许CORS.
旁白: Twitter可以通过这种代理吗?我必须假设,因为Codebird 列在他们推荐的库中.
代理通过开发人员的一个服务器,这很好,但我注意到它偶尔会下降几个小时,有时一整天.一旦我的应用程序投入生产,这是不可接受的,所以我需要自托管代理以获得更多控制权.
幸运的是,它们也为代理提供了源代码.不幸的是,PHP不是一个选择.所以我试图将它移植到CFML,这是我当前最好的选择(我也可以考虑Node.js和Ruby,虽然我对两者都不太熟悉,这就是为什么我现在选择了CFML )
基本上它归结为我试图将此脚本移植到CFML.以下是我到目前为止所做的,但我遇到的问题我将在代码下面描述.
<cfscript>
try{
header(name="Access-Control-Allow-Origin", value="*");
header(name="Access-Control-Allow-Headers", value="Origin, X-Authorization");
header(name="Access-Control-Allow-Methods", value="POST, GET, OPTIONS");
method = cgi.request_method;
if (method == 'OPTIONS'){
abort;
}
path = 'https://api.twitter.com' & cgi.path_info;
headers = [{name="Expect", value=""}];
req_headers = getHTTPRequestData().headers;
req_body = getHTTPRequestData().content;
if (isBinary(req_body)){
req_body = charsetEncode(req_body, "UTF-8");
}
if (structKeyExists(req_headers, 'X-Authorization')){
arrayAppend(headers, { name='Authorization', value=req_headers['X-Authorization'] });
}
response = http_wrapper(method, path, headers, req_body);
code = val( response.statusCode );
msg = trim( replace(response.statusCode, code, '') );
twitter_headers = listToArray(structKeyList( response.responseHeader ));
for (i = 1; i <= arrayLen(twitter_headers); i++){
if (twitter_headers[i] == 'set-cookie'){ continue; }
header(name=twitter_headers[i], value=response.responseHeader[twitter_headers[i]]);
}
header(statusCode=code, statusText=msg);
respond(response.filecontent);
}catch(any e){
application.bugService.notifyService(
message = "Error in Twitter Proxy"
,severityCode = "ERROR"
,exception = e
);
header(statusCode=500,statusText="Proxy Error");
writeDump(var={error=e,twitter_response=response}, format='text');
}
</cfscript>
<cffunction name="http_wrapper">
<cfargument name="method" />
<cfargument name="path" />
<cfargument name="headers" />
<cfargument name="body" />
<cfset var local = {} />
<cfhttp method="#arguments.method#" url="#arguments.path#" result="local.result">
<cfloop from="1" to="#arrayLen(arguments.headers)#" index="local.i">
<cfhttpparam type="header" name="#arguments.headers[i].name#" value="#arguments.headers[i].value#" />
</cfloop>
<cfhttpparam type="body" value="#arguments.body#" />
</cfhttp>
<cfreturn local.result />
</cffunction>
<cffunction name="header">
<cfheader attributeCollection="#arguments#" />
</cffunction>
<cffunction name="respond">
<cfargument name="body" />
<cfcontent reset="true" /><cfoutput>#body#</cfoutput><cfabort/>
</cffunction>
Run Code Online (Sandbox Code Playgroud)
Expect在转发请求时命名为Twitter,据我所知,空值.如果我包含这个标题,我得到这个回复:417 Expectation Failed.Expect标题,我的代理请求得到401响应.重要的是要注意我正在使用已经针对提供的PHP代理进行测试的客户端代码并且工作正常.为了使用我自己的代理,我按如下方式设置了我的Codebird实例:
var cb = new Codebird;
cb.setProxy('https://mydomain.com/api/v1/proxy/twitter.cfm/');
cb.setConsumerKey(key, secret);
Run Code Online (Sandbox Code Playgroud)
Chrome调试工具中的网络请求如下所示:
请求网址: https ://mydomain.com/api/v1/proxy/twitter.cfm/oauth/request_token
请求方法: POST
状态码: 401未经授权的
请求标头
接受:*/*
Accept-Encoding: gzip,deflate,sdch
Accept -Language: en-US,en; q = 0.8
连接: keep-alive
内容长度: 61
内容类型: application/x-www-form-urlencoded
主机: mydomain.com
来源: null
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5)AppleWebKit/537.36(KHTML,与Gecko一样)Chrome/28.0.1500.95 Safari/537.36
X-Authorization: OAuth oauth_consumer_key ="..........",oauth_nonce ="PqK4KPCc ",oauth_signature ="B%2BQ .............. b08%3D",oauth_signature_method ="HMAC-SHA1",oauth_timestamp ="1376507615",oauth_version ="1.0"
表格数据:
oauth_callback : http ://mydomain.com/twitter-login
您可以看到X-Authorization标头包含在请求中,据我所知,它是完整和正确的,在第一个代码示例中,您可以看到此请求标头随后作为Authorization标头转发到Twitter .
我无法弄清楚为什么我会收到401回复.该文件似乎并没有表明一个Expect头是必需的,所以我假设我可以忽略它.(事实上,就我公认的生锈的PHP知识而言,它实际上并没有在PHP版本中发送......)
但如果是这样的话,我为什么要回401呢?其他一切对我来说都是正确的......
根据Adam的评论,我忘了注意到我也故意忽略了所设置的CURL选项(我假设CFHTTP将为我处理所有这些).我现在将通过并记录每个正在使用的文件,并确保CFHTTP涵盖基础:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
Run Code Online (Sandbox Code Playgroud)
TRUE将传输作为curl_exec()的返回值的字符串返回,而不是直接输出.
这是一个写得不好的文档(CF偶尔也会有罪),但似乎表明如果设置了此选项,结果将被返回而不是附加到响应缓冲区.校验; CFHTTP默认情况下会这样做.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
Run Code Online (Sandbox Code Playgroud)
TRUE跟随服务器作为HTTP标头的一部分发送的任何"Location:"标头(注意这是递归的,PHP将跟随它发送的"Location:"标头,除非设置了CURLOPT_MAXREDIRS).
等效的CFHTTP设置为redirect="true"(默认为true).这是一个不匹配,因为PHP版本说不遵循重定向.我会记住这一点,但严重怀疑这是导致我的401.
curl_setopt($ch, CURLOPT_HEADER, 1);
Run Code Online (Sandbox Code Playgroud)
TRUE在输出中包含标头.
检查,CFHTTP在响应中包含标题.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
Run Code Online (Sandbox Code Playgroud)
FALSE阻止cURL验证对等方的证书.可以使用该CURLOPT_CAINFO选项指定要验证的备用证书,也可以使用该选项指定证书目录CURLOPT_CAPATH.
CFHTTP确实验证了SSL证书,正如我在评论中指出的那样,似乎已经导入了必要的证书.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
Run Code Online (Sandbox Code Playgroud)
1检查SSL对等证书中是否存在公用名.2检查是否存在公用名,并验证它是否与提供的主机名匹配.在生产环境中,此选项的值应保持为2(默认值).
我不肯定这是在检查什么,但我不相信CFHTTP有任何相关设置,所以我现在假设这项检查正在进行(或者不是我的问题的一个促成因素).
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/cacert.pem');
Run Code Online (Sandbox Code Playgroud)
包含一个或多个证书以验证对等方的文件的名称.这只有在与之结合使用时才有意义
CURLOPT_SSL_VERIFYPEER.
正如我之前和评论中所提到的,随代理源提供的PEM文件已包含在我的配置中并正在验证.
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
Run Code Online (Sandbox Code Playgroud)
要以格式设置的HTTP标头字段数组
array('Content-type: text/plain', 'Content-length: 100')
检查:我正在将标题传递给Twitter.
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
Run Code Online (Sandbox Code Playgroud)
TRUE跟踪句柄的请求字符串.
什么?根据设置名称,我认为这意味着在输出中包含标题(检查,CFHTTP会这样做),但文档没有意义.
所以这似乎排除了卷曲设置作为一个可能的问题.
小智 0
不确定您对 Twitter API 进行了多少研究,但他们已经放弃了对公共请求的支持,现在一切都必须使用注册的应用程序进行授权。你可以在这里注册一个dev.Twitter
我可以在这里看到您想要实现的目标,我有一个基本的 CFC,它演示了对 twitter API 的有效 http 调用,添加您的密钥和机密,您可以将 twitterEndpoint 变量更改为不同的选项并查看不同的响应。- 希望这可以帮助。
基本 Twitter CFC - 请注意,这仅在 OpenBD CFML 引擎上进行了测试