使用 PHP 代理从 del.icio.us API 装载 XML
因为浏览器内置的安全限制不允许从外部 URL 装载 Web 页面(例如,在访问 google.com 时,通过 Ajax 装载 yahoo.com),所以必须通过代理实现 del.icio.us API。PHP 的 CURL 很适合完成这个任务。下面就来实现代理。
下面要创建的代理的作用仅仅是获取一个 URL 的内容并向用户显示,不做任何进一步处理。创建新文件 proxy.php 并把它保存在 superPage.html 文件所在的目录中。按照清单 5 定义代理。
function getContent( $url ){
$curl = curl_init();
$deliciousUser = ' your_username_here ' ;
$deliciousPass = ' your_password_here ' ;
$header [ 0 ] = " Accept:text/xml,application/xml,application/xhtml+xml, " ;
$header [ 0 ] .= " text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 " ;
$header [] = " Cache-Control:max-age=0 " ;
$header [] = " Connection:keep-alive " ;
$header [] = " Keep-Alive:300 " ;
$header [] = " Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7 " ;
$header [] = " Accept-Language:en-us,en;q=0.5 " ;
$header [] = " Pragma: " ;
curl_setopt( $curl , CURLOPT_URL , $url );
curl_setopt( $curl , CURLOPT_USERAGENT , " imTestingAnApp " );
curl_setopt( $curl , CURLOPT_HTTPHEADER , $header );
curl_setopt( $curl , CURLOPT_REFERER , ' http://www.my-homepage.com ' );
curl_setopt( $curl , CURLOPT_ENCODING , ' gzip,deflate ' );
curl_setopt( $curl , CURLOPT_AUTOREFERER , true );
curl_setopt( $curl , CURLOPT_RETURNTRANSFER , 1 );
curl_setopt( $curl , CURLOPT_CONNECTTIMEOUT , 5 );
curl_setopt( $curl , CURLOPT_TIMEOUT , 5 );
curl_setopt( $curl , CURLOPT_USERPWD ,
$deliciousUser . " : " . $deliciousPass );
curl_setopt( $curl , CURLOPT_SSL_VERIFYPEER , false );
curl_setopt( $curl , CURLOPT_SSL_VERIFYHOST , false );
curl_setopt( $curl , CURLOPT_GET , 1 );
$html = curl_exec( $curl );
$info = curl_getinfo( $curl );
curl_close( $curl );
$return [ ' response ' ] = $html ;
$return [ ' info ' ] = $info ;
return $return ;
}
header ( " Content-Type:text/xml " );
$url = urldecode ( $_GET [ ' url ' ]);
$url2 = $_GET [ ' url2 ' ] != '' ?
' ?url= ' . str_replace ( ' ' , ' + ' , $_GET [ ' url2 ' ]) : '' ;
$description = $_GET [ ' description ' ] != '' ?
' &description= ' . stripslashes ( str_replace ( ' ' , ' + ' ,
$_GET [ ' description ' ])) : '' ;
$tags = $_GET [ ' tags ' ] != '' ?
' &tags= ' . str_replace ( ' ' , ' + ' , $_GET [ ' tags ' ]) : '' ;
$extended = $_GET [ ' extended ' ] != '' ?
' &extended= ' . stripslashes ( str_replace ( ' ' , ' + ' ,
$_GET [ ' extended ' ])) : '' ;
$old = $_GET [ ' old ' ] != '' ? ' ?old= ' . $_GET [ ' old ' ] : '' ;
$new = $_GET [ ' new ' ] != '' ? ' &new= ' . $_GET [ ' new ' ] : '' ;
$tag = $_GET [ ' tag ' ] != '' ?
' ?tag= ' . str_replace ( ' ' , ' + ' , $_GET [ ' tag ' ]) : '' ;
$url = $url . $url2 . $description . $tags . $extended . $old . $new . $tag ;
if ( $url != '' ){
$data = getContent( $url );
echo $data [ ' response ' ];
}
?>
首先请注意 getContent
函数中的 $header 变量。在这里设置头部基本上是为了尽可能地模拟浏览器。然后设置几个 curl 选项,其中一些选项不是必需的,但是您应该注意以下选项:
-
CURLOPT_URL
—— 指定要获取哪个 URL 的内容。 -
CURLOPT_USERAGENT
—— 指定请求 Web 页面的用户代理。del.icio.us 指出一些默认的用户代理有时候会被阻塞,所以最好创建自己的用户代理。 -
CURLOPT_USERPWD
—— 在这里指定 del.icio.us 帐户的用户名和密码。 -
CURLOPT_GET
—— 指定使用GET
方法发出请求。注意,对于添加或删除书签等操作,GET
不一定是合适的请求方法,但是因为将用 JavaScript 处理代理 URL,通过链接删除书签的可能性不大。
接下来,注意 清单 5 中 getContents
函数后面的代码。首先,按照 JavaScript XML DOM 解析器的要求发送头部(“text/xml”)。然后按照 API 调用的要求,从 GET
请求(稍后将用 JavaScript 实现请求)获取 URL 和其他变量。最后,重新构造 URL 并把 URL 传递给 getContent($url)
函数。
接下来,看看从给定的 URL 装载 XML 和传递回 XML 文档的代码。
正如在前面看到的,用来填充哈利波特读书俱乐部超级页面中的数据的许多 del.icio.us API 都返回 XML。因此,需要把 XML 装载进 JavaScript Document Object Model(DOM)中,从而获得所需的数据并在适当的 div
元素中显示。接下来,在 superPage.html 页面中定义 JavaScript 代码,见清单 6。
...
< scriptsrc = " http://maps.google.com/maps?file=api&v=2&key=
ABQIAAAAXpDdw53sBIu0TzqJscmbxhSKosI2eZOba2P8iIPEPpIkOLlzQhTmc61yB7db5hq2aItkrpqUFq-y3Q "
type = " text/javascript " ></ script >
< scripttype = " text/javascript " >
function loadXML(fileName) ... {
varxmlDoc;
if(window.ActiveXObject)...{
xmlDoc=newActiveXObject("Microsoft.XMLDOM");
}
elseif(document.implementation&&
document.implementation.createDocument)...{
xmlDoc=document.implementation.createDocument("","",null);
}
else...{
alert('Unsupportedbrowser');
}
xmlDoc.async=false;
xmlDoc.load(fileName);
return(xmlDoc);
}
首先要包含一个 Google JavaScript 文件,这个文件支持装载不需要任何 XML 处理的 Web 页面。下面的 loadXML
函数是一个跨浏览器(Mozilla、Internet Explorer)的 JavaScript 函数,它用来装载返回 XML 的 URL(fileName
)。最后要记住一点,只能把先通过代理的 URL 传递给这个函数,否则这个函数不起作用。
接下来,编写在 清单 3 中首次出现的 showHTML
函数,在浏览器面板中装载 Web 页面。
既然已经建立了通过代理装载 XML 的 JavaScript 功能,现在要创建一个通过代理装载 Web 页面的函数。编写清单 7 所示的 JavaScript 代码。
GDownloadUrl(url,function(response,responseCode)...{
if(type=='HTTPcontent')
document.getElementById("HTMLcontent").innerHTML=response;
elseif(type=='senddata')
alert(response);
});
}
function showHTML() ... {
varurl="proxy.php?url=";
url=url+document.getElementById('currentHTMLpage').value;
getResponse(url,'HTTPcontent');
}
首先看一下 showHTML
。这个函数设置一个指向 PHP 代理脚本的 URL。然后,把页面顶部的文本框(见 图 3 和 图 5)中请求的 URL 附加到代理 URL 的末尾,并调用 getResponse
函数。注意,getResponse
函数调用 Google JavaScript 库中的一个函数。当 Google 函数返回数据时,调用内部函数,把 HTMLcontent
div 的 HTML 设置为响应,从而显示 图 3 所示的页面。
现在已经编写了 Web 页面浏览器所需的所有功能。您可以试着在哈利波特读书俱乐部超级页面中装载 Web 页面了!
接下来,要开始使用 del.icio.us Web API 了!
使用 API
tags
API 可以获取和重命名读书俱乐部的标记。在本节中,我们要定义 reload
函数(见 清单 3)和 renameTags
函数(见 清单 4),还要开始定义 processXML
函数。首先使用 Get
函数。
使用 tags
API 的 Get
函数装载读书俱乐部 del.icio.us 帐户中的所有标记,并在超级页面上依次显示它们。定义清单 8 所示的 JavaScript。
setTimeout("reload2()",4000);
}
function reload2() ... {
varurl="proxy.php?url=https://api.del.icio.us/v1/tags/get";
varxmlDoc=loadXML(url);
varstring=processXML(xmlDoc,"tags");
document.getElementById("tags-div-1").innerHTML=string;
string=processXML(xmlDoc,"renameTags");
document.getElementById("tags-div-2").innerHTML=string;
document.getElementById("links-div-1").innerHTML='';
document.getElementById("links-div-2").innerHTML='';
}
这里有两个函数。第一个函数 reload()
在修改标记或删除链接之后调用,用来获取帐户中当前的标记。注意,这个函数仅仅在 4 秒的延迟之后调用 reload2()
。reload2()
函数使用 tags/get URL 获取 del.icio.us 帐户中的所有标记。然后,在适当的 div
元素中显示它们。
在清单 8 的 reload2()
函数中,还要注意两个 processXML
函数调用中的第二个参数。这允许使用一个函数实现相似的目标。我们将用这个函数构造 HTML 来替换以下 div
元素:tags-div-1
和 tags-div-2
。processXML
函数的定义见清单 9。
if(type=='tags')...{
vartagStr='';
vartags=xmlDoc.getElementsByTagName("tag");
for(vari=0;i<tags.length;i++)...{
vartagName=tags.item(i).getAttribute('tag');
tagStr=tagStr+'<inputtype="checkbox"name="'+tagName+'"/>'+
tagName+"<br/>";
}
returntagStr;
}
elseif(type=='renameTags')...{
vartagStr='';
vartags=xmlDoc.getElementsByTagName("tag");
for(vari=0;i<tags.length;i++)...{
vartagName=tags.item(i).getAttribute('tag');
tagStr=tagStr+'<inputsize="10"name="'+tagName+'"/>'+
"<br/>";
}
returntagStr;
}
...
在 清单 8 中调用 loadXML
,装载 xmlDoc
;然后调用 processXML
执行解析(type
参数设置为 tags
)。然后从文档中获取名为 tag
的所有子元素,为每个 tag
创建一个 HTML 输入元素,其中包含一个 checkbox
和 tagname
(这些内容依次保存在 tagStr
中)。循环遍历所有标记元素之后,返回 tagStr
并把它设置为 id 是 tags-div-1
的 div
的 HTML 内容。然后第二次调用 processXML
函数(renameTags
作为 type 属性),获取用于标记重命名的文本框,把这个调用的结果设置为 id 是 tags-div-2
的 div
的 HTML 内容。reload2()
函数最后清空显示书签的 div
元素。
以上代码的效果见图 6。
可以看到,在 tags-div-1
div
元素中显示每个标记和复选框,在 tags-div-2 div
元素中显示用于重命名每个标记的输入框。
接下来,看看处理 RENAME TAGS! 按钮所需的代码。
为了重命名读书俱乐部中的标记,需要实现 renameTags
函数。按照清单 10 定义这个函数。
varurl="proxy.php?url=https://api.del.icio.us/v1/tags/rename";
inputTags=document.getElementById("tags-div-2")
.getElementsByTagName("input");
for(vari=0;i<inputTags.length;i++)...{
vartag=inputTags.item(i);
if(tag.value!='')...{
varsendUrl=url+'&old='+tag.getAttribute('name')+
'&new='+tag.value;
getResponse(encodeURI(sendUrl),'senddata');
}
}
reload();
}
在 图 6 所示的文本框中输入新的标记名(非空)之后,通过文本框的名称(tag.getAttribute('name')
)获得当前名称,通过文本框的值(tag.value
)获得新的名称。然后,设置要发送给代理的 URL,对 URL 进行编码并以 senddata
作为类型调用 getResponse
。注意,这仅仅在一个 JavaScript 弹出窗口中显示代理返回的结果。最后,通过 reload()
函数重新装载标记。
为了测试重命名功能,在第一个框中输入 dealio(见 图 6)并单击 RENAME TAGS!。应该会看到图 7 所示的 JavaScript 弹出窗口。
图 7. 成功的标记重命名
另外,超级页面的 tags-div-1
和 tags-div-2 div
元素应该会成功地重新装载,显示重命名后的标记,见图 8.
图 8. 重命名后的标记
接下来,看看如何实现 posts API 来管理哈利波特书签。