Error: Failed to load processor TracNav
No macro or processor named 'TracNav' found

Ce document est aussi disponible en [Français


GET & Authentication

GET

To browse the public marks posted on Blogmarks.net just fetch this URL :

http://api.blogmarks.net/marks

By default, the last 30 public marks posted on blogmarks.net are sent.

Corresponding to the following parameters :

  • last : 30
  • order_type : DESC
  • order_by : created

And so the following URL :

http://api.blogmarks.net/marks?last=30&order_type=DESC&order_by=created

So you can grab the 10 most popular marks of all time, by fetching this URL :

http://api.blogmarks.net/marks?last=10&order_by=popularity

Let's write our first HTTP query and fetch the last mark :

GET /marks?last=1 HTTP/1.0
Host: api.blogmarks.net
Accept: application/atom+xml

The server response :

HTTP/1.1 200 OK
Date: Mon, 07 Mar 2005 19:32:10 GMT
Server: Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.3.9-1.dotdeb.3
X-Powered-By: PHP/4.3.9-1.dotdeb.3
Content-length: 1293
Connection: close
Content-Type: text/xml; charset=utf-8

<?xml version="1.0" encoding="UTF-8"?>
<feed
version="draft-ietf-atompub-format-05:do not deploy"
xmlns="http://purl.org/atom/ns#draft-ietf-atompub-format-05"
xmlns:bm="http://api.blogmarks.net/ns#">
<head>
	<title>Last public marks</title>
	<link rel="alternate" type="application/xhtml+xml" href="?last=1"/>
	<link rel="next" type="application/atom+xml" href="http://api.blogmarks.net/marks?last=1&amp;offset=1&amp;order_type=DESC&amp;order_by=created"/>
	<updated>2005-03-07T20:23:04Z</updated>
</head>
<entry>
	<id>tag:blogmarks.net,2005:marks,31171</id>
	<title type="TEXT">Kevin Kelly -- Cool Tools:Wall Full of Whiteboard</title>
	<link rel="related" href="http://www.kk.org/cooltools/archives/000679.php" type="text/html"/>
	<link rel="alternate" href="http://blogmarks.net/user/delicious.popular/archives/2005/03/#mark31171" type="application/xhtml+xml" title="Kevin Kelly -- Cool Tools:Wall Full of Whiteboard"/>
	<link rel="image" href="http://www.blogmarks.net/screenshots/2005/03/07/2d3eb782512a6aff2540f74a0a32bd3d.png" type="image/png"/>
	<updated>2005-03-07T20:23:04Z</updated>
	<published>2005-03-07T20:23:04Z</published>
	<author><name>delicious.popular</name></author>
	<edit>http://api.blogmarks.net/atom/marks/31171</edit>
	<bm:created>2005-03-07T20:23:04Z</bm:created>
</entry>
</feed>

If you want to write this in a script, we recommand you to use an HTTP library like Pear HTTP:Request (in case you're using PHP) :

<?php

require_once "HTTP/Request.php";

$req =& new HTTP_Request("http://api.blogmarks.net/marks?last=1");
$req->addHeader("Accept", 'application/atom+xml');

$response = $req->sendRequest();

if (PEAR::isError($response)) {
	echo $response->getMessage();
} else {
	$code = $req->getResponseCode();
	switch ( $code ) {
	  case 200:
	    $xml = $req->getResponseBody();
	    // Handle the resulting Atom response here
	    echo $xml;
	    break;
	  default:
	    echo $code . " Error\n";
	    break;
	}
	
}

?>

For your curiosity, in vanilla PHP, you can write this (very basic, no error handling) :

<?php

$request  = 'GET /marks?last=1 HTTP/1.0' . "\n";
$request .= 'Host: api.blogmarks.net' . "\n";
$request .= 'Accept: application/atom+xml' . "\n";
$request .= "\n";

$fp = fsockopen('api.blogmarks.net', 80, $errno, $errstr, 30);

fputs($fp,$request);

$response = '';
while ( !feof ( $fp ) ) {
	$line = fgets ($fp, 128);
	$response .= $line;
}
fclose($fp);

echo $response;

?>

Authentication

Now, imagine you want to fetch your private marks and private tags. This feature require authentication. As advised in the Atom authentication tutorial by Mark Pilgrim, we'll use WSSE Username Token authentication. For detailed explanation about WSSE authentication, the tutorial is a must read.

We start with 4 variables :

  • $Username : znarf
  • $Password : foo
  • $Nonce (a cryptographically random string ) : 15253654
  • $CreationTimestamp (the current time in W3CDTF format) : 2004-03-08T17:11:42Z

In our implementation we use the md5 hash of the password. If you have the original password hash it, else just use the hashed one.

So eventually :

  • $PasswordHash = md5( $Password );

We create the password digest :

  • $PasswordDigest = Base64 ( SHA1 ( $Nonce + $CreationTimestamp + $PasswordHash ) )

Basically we add 2 lines in the HTTP header and we are authenticated. Note we've set the private parameter to TRUE to request the private marks and private tags.

GET /marks?last=30&private=true HTTP/1.0
Host: api.blogmarks.net
Accept: application/atom+xml
Authorization: WSSE profile="UsernameToken"
X-WSSE: UsernameToken Username="$Username", PasswordDigest="$PasswordDigest", Nonce="$Nonce", Created="$CreationTimestamp"

The corresponding PHP code is :

<?php

$Username = 'znarf';
$Password = 'foo';
$Nonce = rand( 1 , 100000000000000 );
$CreationTimestamp = date('Y-m-d\Th:i:s\Z');

$PasswordHash = md5( $Password );

$PasswordDigest = base64_encode( sha1( $Nonce . $CreationTimestamp . $PasswordHash  ) );

require_once "HTTP/Request.php";

$req =& new HTTP_Request("http://api.blogmarks.net/marks?last=1&private=true");
$req->addHeader("Accept", 'application/atom+xml');
$req->addHeader('Authorization', 'WSSE profile="UsernameToken"');
$req->addHeader('X-WSSE', 'UsernameToken Username="' . $Username . '",
      PasswordDigest="' . $PasswordDigest . '", Nonce="' . $Nonce . '", Created="' . $CreationTimestamp . '"');

$response = $req->sendRequest();

if (PEAR::isError($response)) {
	echo $response->getMessage();
} else {
	$code = $req->getResponseCode();
	switch ( $code ) {
	  case 200:
	    $xml = $req->getResponseBody();
	    // Handle the resulting Atom response here
	    echo $xml;
	    break;
	  default:
	    echo $code . " Error\n";
	    break;
	}
	
}

?>

Note that we've handled directly the authentication but the best is to use core components of your framework of choice.


See also : AtomApiTutorial/Post, AtomApiTutorial/Put, AtomApiTutorial/Delete