SlideShare a Scribd company logo
1 of 80
AtomPub: testing your server
     implementation

        David Calavera
         11870.com
vanity slide


‣ software architect, 11870.com

‣ open source “aholic”: Hudson, Netbeans...

‣ apache abdera commiter
Agenda


‣ atom publishing protocol, introduction

‣ testing the specification

‣ useful tools, putting it all together
atom publishing protocol
Atom publishing protocol




 “an application-level protocol
for publishing and editing web
          resources”
atom format
Wordpress api

<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<feed xmlns=quot;http://www.w3.org/2005/Atomquot;
      xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;>
<id>http://www.verbosemode.com/wp-app.php/posts</id>
<updated>2007-11-13T22:07:43Z</updated>
<title type=quot;textquot;>Verbose mode</title>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
       xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;>
  <id>http://www.verbosemode.com/?p=3</id>
  <title type=quot;textquot;>Google Test Automation Conference 08</title>
  <updated>2007-11-13T22:07:43Z</updated>
  <published>2007-11-04T11:38:28Z</published>
  <app:edited>2007-11-13T22:07:43Z</app:edited>
  <link rel=quot;editquot;
      href=quot;http://www.verbosemode.com/wp-app.php/post/3quot; />
  ...
Mule Galaxy api

<entry xmlns=quot;http://www.w3.org/2005/Atomquot;>
  <link rel=quot;editquot;
     href=quot;/api/registry/Workspace/hello_world.wsdl;atomquot;/>
  <id>urn:galaxy:artifact:5a7dc836-32f1-4d97-b593-8f510bfb28c4</id>
  <title type=quot;textquot;>hello_world.wsdl</title>
  <updated>2008-02-21T20:04:17.481Z</updated>
  <author><name>Galaxy</name></author>
  <summary type=quot;xhtmlquot; />
  <content type=quot;application/xmlquot;
      src=quot;/api/registry/Workspace/hello_world.wsdlquot; />
  <link href=quot;/api/registry/Workspace/hello_world.wsdlquot;
      rel=quot;edit-mediaquot; />
  <metadata xmlns=quot;http://galaxy.mule.org/1.0quot;>
    <property name=quot;wsdl.servicequot; locked=quot;truequot;>
      <value>HelloWorldService</value>
    </property>
    ...
youTube Data api
http methods



   POST

   GET

   PUT

   DELETE
extensible protocol
atom extensions

     ‣ open search
<?xml version='1.0'
<feed xmlns=quot;http://www.w3.org
    xmlns:os=quot;http://a9.com/-/
spec/opensearchquot;
                                      ‣  geoRSS
  <os:itemsPerPage>10          <?xml version='1.0' encoding='UTF8'?>
  <os:totalResults>10          <entry xmlns=quot;http://www.w3.org
</feed>                            xmlns:geo=quot;http://www.georss.org
                                 <geo:point>36.331445 -119.64592
                               </entry>


          ‣ AtomPub multipart media creation
   <?xml version='1.0' encoding='UTF8'?>
   <service xmlns=quot;http://www.w3.org/2007/appquot;
       xmlns:atom=quot;http://www.w3.org/2005/Atomquot; >
     <workspace>
       <collection href=quot;/imagesquot;>
         <accept alternate=quot;multipart-createdquot; >image/*</accept>
atom publishing protocol

     how does it work?
introspective protocol
introspective protocol

<?xml version='1.0' encoding='UTF8'?>
<service xmlns=quot;http://www.w3.org/2007/appquot;
    xmlns:atom=quot;http://www.w3.org/2005/Atomquot; >
  <workspace>
    <atom:titletype=quot;textquot;>
      AtomPub in the GTAC
    </atom:title>
    <collection href=quot;/sessionsquot;>
      <atom:title type=quot;textquot;>
        Gtac sessions
      </atom:title>
      <accept>application/atom+xml;type=entry</accept>
      <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; >
        <atom:category term=quot;testingquot;/>
        <atom:category term=quot;gtacquot;/>
      </categories>
    </collection>
  </workspace>
</service>
introspective protocol

<?xml version='1.0' encoding='UTF8'?>
<service xmlns=quot;http://www.w3.org/2007/appquot;
    xmlns:atom=quot;http://www.w3.org/2005/Atomquot; >
  <workspace>
    <atom:titletype=quot;textquot;>
      AtomPub in the GTAC
    </atom:title>
    <collection href=quot;/sessionsquot;>
      <atom:title type=quot;textquot;>
        Gtac sessions
      </atom:title>
      <accept>application/atom+xml;type=entry</accept>
      <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; >
        <atom:category term=quot;testingquot;/>
        <atom:category term=quot;gtacquot;/>
      </categories>
    </collection>
  </workspace>
</service>
introspective protocol

<?xml version='1.0' encoding='UTF8'?>
<service xmlns=quot;http://www.w3.org/2007/appquot;
    xmlns:atom=quot;http://www.w3.org/2005/Atomquot; >
  <workspace>
    <atom:titletype=quot;textquot;>
      AtomPub in the GTAC
    </atom:title>
    <collection href=quot;/sessionsquot;>
      <atom:title type=quot;textquot;>
        Gtac sessions
      </atom:title>
      <accept>application/atom+xml;type=entry</accept>
      <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; >
        <atom:category term=quot;testingquot;/>
        <atom:category term=quot;gtacquot;/>
      </categories>
    </collection>
  </workspace>
</service>
introspective protocol

<?xml version='1.0' encoding='UTF8'?>
<service xmlns=quot;http://www.w3.org/2007/appquot;
    xmlns:atom=quot;http://www.w3.org/2005/Atomquot; >
  <workspace>
    <atom:titletype=quot;textquot;>
      AtomPub in the GTAC
    </atom:title>
    <collection href=quot;/sessionsquot;>
      <atom:title type=quot;textquot;>
        Gtac sessions
      </atom:title>
      <accept>application/atom+xml;type=entry</accept>
      <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; >
        <atom:category term=quot;testingquot;/>
        <atom:category term=quot;gtacquot;/>
      </categories>
    </collection>
  </workspace>
</service>
POST /sessions

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <app:edited>2007-12-13T18:30:02Z</app:edited>
  <content>
    testing atomPub servers
  </content>
</entry>
POST /sessions

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <app:edited>2007-12-13T18:30:02Z</app:edited>
  <content>
    testing atomPub servers
  </content>
</entry>




response.code == 201
response['Location'] == 'http://gtac.com/sessions/atomPub-testing'
retrieve
GET /sessions/atomPub-testing
uri = Uri.parse response['Location']

Net::HTTP.start(uri.host, uri.port) do |http|
  @entry = http.request_get uri.path
end

          or
@doc = REXML::Document.new @feed
link = REXML::XPath.first doc.root, 'entry/link[@rel=quot;editquot;]'
uri = Uri.parse link

Net::HTTP.start(uri.host, uri.port) do |http|
  @entry = http.request_get uri.path
end


          or
if response['Location'] == response['Content-Location']
  @entry = response.body
end
GET /sessions/atomPub-testing




@doc = REXML::Document.new @feed
@entry = REXML::XPath.first
doc.root, 'entry'
modify
PUT /sessions/atom-pub

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
      href=quot;http://localhost/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <app:edited>2007-12-13T18:30:02Z</app:edited>
  <content type=quot;htmlquot;>
    <div>
     testing
<a href=quot;http://tools.ietf.org/html/rfc5023quot;>atomPub</a> servers
    </div>
  </content>
</entry>



                      response.code == 204
delete
DELETE /sessions/atom-pub

uri = Uri.parse response['Location']

Net::HTTP.start(uri.host, uri.port) do |http|
  http.request Net::HTTP::Delete.new(uri.path)
end




                      response.code == 200
what would happend with media?
Media




response.code == 201
response['Location'] == 'http://gtac.com/sessions/media.atom'




<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot; href=quot;http://gtac.com/sessions/media.atomquot;/>
  <link rel=quot;edit-mediaquot; href=quot;http://gtac.com/sessions/mediaquot;/>
testing the specification

 testing and best practices
status codes
405 Method not allowed
415 Unsupported media type
other interesting codes




200 201 204 301
400 401 403 404
405 409 415 500
cache control
building ids properly
building ids properly


‣ valid URI, rfc 2693

‣ globally unique

‣ never change
building ids properly




<id>http://gtac.com/sessions/atomPub</id>
building ids properly


“If you think that there's a good
chance your URIs will change, you
shouldn't use them for IDs. But, if
you think that, you should also
bloody well be looking for better
software or hosting or whatever.”

                          -- Tim Bray
building ids properly




“never mind the URI here’s my UUID”

                           -- Bill de hÓra
building ids properly




<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
building ids properly




assert
/^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)
(?:?([^#]*))?(?:#(.*))?/.match(id)[0]
managing dates and sorting
managing dates and sorting

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <created>2007-12-10T18:30:02Z</created>
  <updated>2007-12-13T18:30:02Z</updated>
  <published>2007-12-13T18:55:02Z</published>

</entry>
managing dates and sorting

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <created>2007-12-10T18:30:02Z</created>
  <updated>2007-12-13T18:30:02Z</updated>
  <published>2007-12-13T18:55:02Z</published>
  <app:edited>2007-12-13T18:40:02Z</app:edited>
</entry>
managing dates and sorting

<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<feed xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;>
  <id>http://www.verbosemode.com/wp-app.php/posts</id>
  <updated>2007-11-13T22:07:43Z</updated>
  <entry>
    <updated>2008-06-04T22:07:43Z</updated>
    <published>2008-06-08T11:38:28Z</published>
    <app:edited>2008-07-13T22:07:43Z</app:edited>
    ...
  </entry>
  <entry>
    <updated>2007-11-13T22:07:43Z</updated>
    <published>2007-11-04T11:38:28Z</published>
    <app:edited>2007-11-13T22:07:43Z</app:edited>
    ...
  </entry>
managing dates and sorting




assert
/(d{4})(?:-(d{2}))?(?:-(d{2}))?(?:
([Tt])?(?:(d{2}))?(?::(d{2}))?(?::
(d{2}))?(?:.(d{3}))?)?([Zz])?(?:([+-])
(d{2}):(d{2}))?/.match(date)[0]
managing dates and sorting




<updated>2007-12-13T18:30:02Z</updated>
<updated>2007-12-13T18:30:02Z</updated>
<updated>2007-12-13T18:30:02.25Z</updated>
<updated>2007-12-13T18:30:02+01:00</updated>
<updated>2007-12-13T18:30:02.25+01:00</updated>
checking valid content
checking valid content

def assert_valid_entry(entry)
  assert entry.id.absolute?
  assert_not_nil entry.title
  assert_not_nil entry.updated
  assert_not_nil entry.edited

  unless entry.content
    alternate = REXML::XPath.first entry, 'link[@rel=quot;alternatequot;]'
    assert_not_nil alternate
  else
    assert !entry.content.src.nil? or
      (Base64.decode64(entry.content.text) and !entry.summary.nil?)
  end
end
checking valid content

<entry xmlns=quot;http://www.w3.org/2005/Atomquot;>
  <title type=quot;textquot;>unclean!</title>
  <summary type='xhtml'>
    <div xmlns='http://www.w3.org/1999/xhtml'>
      <p>hey</p>
      <script src='http://www.example.com/xxx' />
      <script>alert('XXX')</script>
      <p id='x1' background=quot;javascript:alert('XSS')quot;>Hey</p>
    </div>
  </summary>
  <content type='xhtml'>
    <div xmlns='http://www.w3.org/1999/xhtml'>
      <p id='x2' style='whatever'>OK</p><object>No No No</object>
      <a href='/no-problemo'>aah</a>
      <a href='javascript:evil'>ouch</a>
    </div>
  </content>
managing media
managing media




<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>????</title>
  <summary>????</summary>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testing.atomquot;/>
  <link rel=quot;edit-mediaquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <app:edited>2007-12-13T18:30:02Z</app:edited>
  <content src=quot;http://gtac.com/managing-media.pngquot;/>
</entry>
managing media

                     request['Slug'] == 'nice picture'




<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>nice picture</title>
  <summary>nice picture</summary>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testing.atomquot;/>
  <link rel=quot;edit-mediaquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <app:edited>2007-12-13T18:30:02Z</app:edited>
  <content src=quot;http://gtac.com/managing-media.pngquot;/>
</entry>
categorizing resources
categorizing resources

<collection href=quot;/sessionsquot;>
  <atom:title type=quot;textquot;>Gtac sessions</atom:title>
  <accept>application/atom+xml;type=entry</accept>
  <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/scheme/privacyquot;>
    <atom:category term=quot;publicquot;/>
    <atom:category term=quot;privatequot;/>
    <atom:category term=quot;friendsquot;/>
    <atom:category term=quot;familyquot;/>
  </categories>
  <categories scheme=quot;http://gtac.com/scheme/tagsquot;>
    <atom:category term=quot;testingquot;/>
    <atom:category term=quot;gtacquot;/>
    <atom:category term=quot;gtac08quot;/>
    <atom:category term=quot;atomquot;/>
    <atom:category term=quot;calaveraquot;/>
  </categories>
</collection>
categorizing resources

<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <created>2007-12-10T18:30:02Z</created>
  <updated>2007-12-13T18:30:02Z</updated>
  <published>2007-12-13T18:55:02Z</published>
  <category scheme=quot;http://gtac.com/scheme/privacyquot;
    term=quot;TRYING TO ADD AN UNEXPECTED CATEGORYquot;/>
</entry>




                      response.code == 409
categorizing resources

<collection href=quot;/sessionsquot;>
  <atom:title type=quot;textquot;>Gtac sessions</atom:title>
  <accept>application/atom+xml;type=entry</accept>
  <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/scheme/privacyquot;>
    <atom:category term=quot;publicquot;/>
    <atom:category term=quot;privatequot;/>
    <atom:category term=quot;friendsquot;/>
    <atom:category term=quot;familyquot;/>
  </categories>
  <categories scheme=quot;http://gtac.com/scheme/tagsquot;>
    <atom:category term=quot;testingquot;/>
    <atom:category term=quot;gtacquot;/>
    <atom:category term=quot;gtac08quot;/>
    <atom:category term=quot;atomquot;/>
    <atom:category term=quot;calaveraquot;/>
  </categories>
</collection>
extending atomPub
extending atomPub

           my document is not valid!!!


<?xml version='1.0' encoding='UTF8'?>
<entry xmlns=quot;http://www.w3.org/2005/Atomquot;
    xmlns:app=quot;http://www.w3.org/2007/appquot;>
  <title>AtomPub testing session</title>
  <link rel=quot;editquot;
     href=quot;http://gtac.com/sessions/atomPub-testingquot;/>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2007-12-13T18:30:02Z</updated>
  <georss:point>36.331445 -119.64592</georss:point>
</entry>
extending atomPub

         my document is not valid!!!

def rnc_validate(schema, document)
  schemaError = StringWriter.new
  errorHandler = ErrorHandlerImpl.new(schemaError)
  properties = PropertyMapBuilder.new
  properties.put(ValidateProperty::ERROR_HANDLER, errorHandler)
  driver = ValidationDriver.new(properties.toPropertyMap,
    CompactSchemaReader.getInstance)
  driver.loadSchema(InputSource.new(StringReader.new(schema)))
  begin
    input = InputSource.new(StringReader.new(document))
    error = schemaError.toString unless driver.validate(input)
  rescue org.xml.sax.SAXParseException
    error = $!.to_s.sub(/n.*$/, '')
  end
  error
end
putting it all together
feed validator
feed validator


          ‣ Atom, RSS, KML, OMPL...

          ‣ recognizes most standard namespaces

          ‣ runs locally as well:
$ svn co http://feedvalidator.googlecode.com/svn/trunk/feedvalidator

$ python src/demo.py http://code.google.com/p/feedvalidator/w/list
feed validator
AppClientTest

          tests basic aspects of atomPub


$ svn co http://feedvalidator.googlecode.com/svn/trunk/apptestsuite/client/
validator/ validator

$ python validator/appclienttest.py --output=results.html
  quot;http://bitworking.org/projects/apptestsite/app.cgi/
service/;service_documentquot;

$ firefox results.html
AppClientTest

         record and play it back!!


$ python validator/appclienttest.py
  --record=./validator/rawtestdata/complete/ --html
  --output=test.html

$ python validator/appclienttest.py
  --playback=./validator/rawtestdata/complete/ --html
  --output=test.html
AppClientTest

         record and play it back!!

$ tree validator/rawtestdata/complete/
validator/rawtestdata/complete/
|-- GET
|   `-- projects
|       `-- apptestsite
|           `-- app.cgi
|                |-- service
|                |   |-- entry
|                |   |   |-- 1.file
|                |   |   |-- 1.file.2
|                |   |   |-- 2.file
|                |   |   |-- 2.file.2
|                |   |   |-- 2.file.3
AppClientTest

html output with links to the specification
AtomPub Test Client

ms windows desktop client
The Atom Publishing Exerciser
The Atom Protocol Excerciser

            rubygem library with more than 50 test cases

$ svn co http://ape.rubyforge.org/svn/trunk ape

$ gem install ape



            command line tasks

$ rake -T

rake ape:go:atom[uri,username,password]
rake ape:go:html[uri,username,password]
rake ape:go:text[uri,username,password]
The Atom Protocol Excerciser

inbuilt web server
The Atom Protocol Excerciser

completely extensible!!


‣ authentication: basic_auth, wsse, googleLogin

‣ formats: text, html, atom

‣ validators
demo!!!
questions?

‣ Blog: http://thinkincode.net
‣ Email: calavera@apache.org
‣ Resources:
  ‣ RFC 5023: http://www.ietf.org/rfc/rfc5023.txt
  ‣ RFC 4287: http://www.ietf.org/rfc/rfc4287.txt
  ‣ RFC 2616: http://www.ietf.org/rfc/rfc2616.txt
  ‣ RFC 2693: http://www.ietf.org/rfc/rfc2693.txt
  ‣ Apache Abdera: http://incubator.apache.org/abdera
  ‣ Feed validator: http://feedvalidator.org
  ‣ AppClientTest: http://code.google.com/p/feedvalidator/wiki/AppClientTest
  ‣ AtomPub test client: http://www.witha.jp/eXeries/software/
  ‣ The APE: http://rubyforge.org/projects/ape
photos
‣ http://flickr.com/photos/visualpanic/2240763525/
‣ http://flickr.com/photos/edgeplot/1529475806/
‣ http://flickr.com/photos/perstephanie/2806654855/
‣ http://flickr.com/photos/giornaletecnologico/1566587705/
‣ http://flickr.com/photos/visualpanic/1474644715/
‣ http://flickr.com/photos/javi_co/2516310892/
‣ http://flickr.com/photos/suttonhoo22/2512983749/
‣ http://flickr.com/photos/xanboozled/784164182/
‣ http://flickr.com/photos/baloncestorrelavega/2736961248/
‣ http://flickr.com/photos/jork85/1776795805/
‣ http://flickr.com/photos/jessefriedman/1435220149/
‣ http://flickr.com/photos/apelad/304197126/
‣ http://flickr.com/photos/apelad/304194299/
‣ http://flickr.com/photos/dw/827997520/
‣ http://flickr.com/photos/lapidim/59044209/
‣ http://flickr.com/photos/visualpanic/365605949/
‣ http://flickr.com/photos/visualpanic/2261768075/
‣ http://flickr.com/photos/drift-words/99645/
‣ http://flickr.com/photos/prawnpie/369727578/
‣ http://flickr.com/photos/laydros/2877137537/
‣ http://flickr.com/photos/bretarnett/75243850/
‣ http://flickr.com/photos/wcouch/2091338695/

More Related Content

What's hot

Pragmatics of Declarative Ajax
Pragmatics of Declarative AjaxPragmatics of Declarative Ajax
Pragmatics of Declarative Ajaxdavejohnson
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate BustersHamletDRC
 
Java to Golang: An intro by Ryan Dawson Seldon.io
Java to Golang: An intro by Ryan Dawson Seldon.ioJava to Golang: An intro by Ryan Dawson Seldon.io
Java to Golang: An intro by Ryan Dawson Seldon.ioMauricio (Salaboy) Salatino
 
PyCon Korea - Real World Graphene
PyCon Korea - Real World GraphenePyCon Korea - Real World Graphene
PyCon Korea - Real World GrapheneMarcin Gębala
 
PyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document GenerationPyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document Generation용선 이
 
Stargate: an interstellar journey to RESTful APIs
Stargate: an interstellar journey to RESTful APIsStargate: an interstellar journey to RESTful APIs
Stargate: an interstellar journey to RESTful APIsFAST
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best PracticesDavid Wheeler
 

What's hot (9)

Pragmatics of Declarative Ajax
Pragmatics of Declarative AjaxPragmatics of Declarative Ajax
Pragmatics of Declarative Ajax
 
Java Boilerplate Busters
Java Boilerplate BustersJava Boilerplate Busters
Java Boilerplate Busters
 
ANT
ANTANT
ANT
 
Java to Golang: An intro by Ryan Dawson Seldon.io
Java to Golang: An intro by Ryan Dawson Seldon.ioJava to Golang: An intro by Ryan Dawson Seldon.io
Java to Golang: An intro by Ryan Dawson Seldon.io
 
PyCon Korea - Real World Graphene
PyCon Korea - Real World GraphenePyCon Korea - Real World Graphene
PyCon Korea - Real World Graphene
 
PyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document GenerationPyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document Generation
 
Struts2.0basic
Struts2.0basicStruts2.0basic
Struts2.0basic
 
Stargate: an interstellar journey to RESTful APIs
Stargate: an interstellar journey to RESTful APIsStargate: an interstellar journey to RESTful APIs
Stargate: an interstellar journey to RESTful APIs
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best Practices
 

Viewers also liked

Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9David Calavera
 
Egyptian Aeraunautical Sports Club Guide
Egyptian Aeraunautical Sports Club GuideEgyptian Aeraunautical Sports Club Guide
Egyptian Aeraunautical Sports Club Guideahmad bassiouny
 
ApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationDavid Calavera
 
Life-feed | final presentation
Life-feed  |  final presentationLife-feed  |  final presentation
Life-feed | final presentationPixelkings
 
Conferencia Rails: Integracion Continua Y Rails
Conferencia Rails: Integracion Continua Y RailsConferencia Rails: Integracion Continua Y Rails
Conferencia Rails: Integracion Continua Y RailsDavid Calavera
 

Viewers also liked (8)

Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9Rubyspec y el largo camino hacia Ruby 1.9
Rubyspec y el largo camino hacia Ruby 1.9
 
JRuby hacking guide
JRuby hacking guideJRuby hacking guide
JRuby hacking guide
 
Egyptian Aeraunautical Sports Club Guide
Egyptian Aeraunautical Sports Club GuideEgyptian Aeraunautical Sports Club Guide
Egyptian Aeraunautical Sports Club Guide
 
ApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub ImplementationApacheCon: Abdera A Java Atom Pub Implementation
ApacheCon: Abdera A Java Atom Pub Implementation
 
My name is Trinidad
My name is TrinidadMy name is Trinidad
My name is Trinidad
 
Trinidad
TrinidadTrinidad
Trinidad
 
Life-feed | final presentation
Life-feed  |  final presentationLife-feed  |  final presentation
Life-feed | final presentation
 
Conferencia Rails: Integracion Continua Y Rails
Conferencia Rails: Integracion Continua Y RailsConferencia Rails: Integracion Continua Y Rails
Conferencia Rails: Integracion Continua Y Rails
 

Similar to AtomPub Server Testing

Kurzeinführung: Atom Publishing Protocol
Kurzeinführung: Atom Publishing ProtocolKurzeinführung: Atom Publishing Protocol
Kurzeinführung: Atom Publishing ProtocolDirk Haun
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructurePamela Fox
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructureguest517f2f
 
Migration testing framework
Migration testing frameworkMigration testing framework
Migration testing frameworkIndicThreads
 
Developing and testing ajax components
Developing and testing ajax componentsDeveloping and testing ajax components
Developing and testing ajax componentsIgnacio Coloma
 
Struts2 course chapter 2: installation and configuration
Struts2 course chapter 2: installation and configurationStruts2 course chapter 2: installation and configuration
Struts2 course chapter 2: installation and configurationJavaEE Trainers
 
Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)Michiel Rook
 
Struts2
Struts2Struts2
Struts2yuvalb
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructureguest517f2f
 
Dan Holevoet, Google
Dan Holevoet, GoogleDan Holevoet, Google
Dan Holevoet, Google500 Startups
 
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM Alfresco Software
 
Web APIs & Google APIs
Web APIs & Google APIsWeb APIs & Google APIs
Web APIs & Google APIsPamela Fox
 
JWU Guest Talk: JavaScript and AJAX
JWU Guest Talk: JavaScript and AJAXJWU Guest Talk: JavaScript and AJAX
JWU Guest Talk: JavaScript and AJAXHilary Mason
 

Similar to AtomPub Server Testing (20)

Kurzeinführung: Atom Publishing Protocol
Kurzeinführung: Atom Publishing ProtocolKurzeinführung: Atom Publishing Protocol
Kurzeinführung: Atom Publishing Protocol
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
 
Migration testing framework
Migration testing frameworkMigration testing framework
Migration testing framework
 
WordPress APIs
WordPress APIsWordPress APIs
WordPress APIs
 
Developing and testing ajax components
Developing and testing ajax componentsDeveloping and testing ajax components
Developing and testing ajax components
 
Struts2 course chapter 2: installation and configuration
Struts2 course chapter 2: installation and configurationStruts2 course chapter 2: installation and configuration
Struts2 course chapter 2: installation and configuration
 
Ajax ons2
Ajax ons2Ajax ons2
Ajax ons2
 
Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)Phing - A PHP Build Tool (An Introduction)
Phing - A PHP Build Tool (An Introduction)
 
Struts2
Struts2Struts2
Struts2
 
Html5
Html5Html5
Html5
 
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
 
DevDays09 Internet Explorer 8
DevDays09 Internet Explorer 8DevDays09 Internet Explorer 8
DevDays09 Internet Explorer 8
 
Html5 Overview
Html5 OverviewHtml5 Overview
Html5 Overview
 
RESTFul IDEAS
RESTFul IDEASRESTFul IDEAS
RESTFul IDEAS
 
Dan Holevoet, Google
Dan Holevoet, GoogleDan Holevoet, Google
Dan Holevoet, Google
 
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM
Enterprise Google Gadgets Integrated with Alfresco - Open Source ECM
 
Web APIs & Google APIs
Web APIs & Google APIsWeb APIs & Google APIs
Web APIs & Google APIs
 
Widgets Tools Keynote
Widgets Tools KeynoteWidgets Tools Keynote
Widgets Tools Keynote
 
JWU Guest Talk: JavaScript and AJAX
JWU Guest Talk: JavaScript and AJAXJWU Guest Talk: JavaScript and AJAX
JWU Guest Talk: JavaScript and AJAX
 

Recently uploaded

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 

Recently uploaded (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 

AtomPub Server Testing

  • 1. AtomPub: testing your server implementation David Calavera 11870.com
  • 2.
  • 3. vanity slide ‣ software architect, 11870.com ‣ open source “aholic”: Hudson, Netbeans... ‣ apache abdera commiter
  • 4. Agenda ‣ atom publishing protocol, introduction ‣ testing the specification ‣ useful tools, putting it all together
  • 6. Atom publishing protocol “an application-level protocol for publishing and editing web resources”
  • 8. Wordpress api <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <feed xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;> <id>http://www.verbosemode.com/wp-app.php/posts</id> <updated>2007-11-13T22:07:43Z</updated> <title type=quot;textquot;>Verbose mode</title> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;> <id>http://www.verbosemode.com/?p=3</id> <title type=quot;textquot;>Google Test Automation Conference 08</title> <updated>2007-11-13T22:07:43Z</updated> <published>2007-11-04T11:38:28Z</published> <app:edited>2007-11-13T22:07:43Z</app:edited> <link rel=quot;editquot; href=quot;http://www.verbosemode.com/wp-app.php/post/3quot; /> ...
  • 9. Mule Galaxy api <entry xmlns=quot;http://www.w3.org/2005/Atomquot;> <link rel=quot;editquot; href=quot;/api/registry/Workspace/hello_world.wsdl;atomquot;/> <id>urn:galaxy:artifact:5a7dc836-32f1-4d97-b593-8f510bfb28c4</id> <title type=quot;textquot;>hello_world.wsdl</title> <updated>2008-02-21T20:04:17.481Z</updated> <author><name>Galaxy</name></author> <summary type=quot;xhtmlquot; /> <content type=quot;application/xmlquot; src=quot;/api/registry/Workspace/hello_world.wsdlquot; /> <link href=quot;/api/registry/Workspace/hello_world.wsdlquot; rel=quot;edit-mediaquot; /> <metadata xmlns=quot;http://galaxy.mule.org/1.0quot;> <property name=quot;wsdl.servicequot; locked=quot;truequot;> <value>HelloWorldService</value> </property> ...
  • 11.
  • 12. http methods POST GET PUT DELETE
  • 14. atom extensions ‣ open search <?xml version='1.0' <feed xmlns=quot;http://www.w3.org xmlns:os=quot;http://a9.com/-/ spec/opensearchquot; ‣ geoRSS <os:itemsPerPage>10 <?xml version='1.0' encoding='UTF8'?> <os:totalResults>10 <entry xmlns=quot;http://www.w3.org </feed> xmlns:geo=quot;http://www.georss.org <geo:point>36.331445 -119.64592 </entry> ‣ AtomPub multipart media creation <?xml version='1.0' encoding='UTF8'?> <service xmlns=quot;http://www.w3.org/2007/appquot; xmlns:atom=quot;http://www.w3.org/2005/Atomquot; > <workspace> <collection href=quot;/imagesquot;> <accept alternate=quot;multipart-createdquot; >image/*</accept>
  • 15. atom publishing protocol how does it work?
  • 17. introspective protocol <?xml version='1.0' encoding='UTF8'?> <service xmlns=quot;http://www.w3.org/2007/appquot; xmlns:atom=quot;http://www.w3.org/2005/Atomquot; > <workspace> <atom:titletype=quot;textquot;> AtomPub in the GTAC </atom:title> <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;> Gtac sessions </atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; > <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> </categories> </collection> </workspace> </service>
  • 18. introspective protocol <?xml version='1.0' encoding='UTF8'?> <service xmlns=quot;http://www.w3.org/2007/appquot; xmlns:atom=quot;http://www.w3.org/2005/Atomquot; > <workspace> <atom:titletype=quot;textquot;> AtomPub in the GTAC </atom:title> <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;> Gtac sessions </atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; > <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> </categories> </collection> </workspace> </service>
  • 19. introspective protocol <?xml version='1.0' encoding='UTF8'?> <service xmlns=quot;http://www.w3.org/2007/appquot; xmlns:atom=quot;http://www.w3.org/2005/Atomquot; > <workspace> <atom:titletype=quot;textquot;> AtomPub in the GTAC </atom:title> <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;> Gtac sessions </atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; > <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> </categories> </collection> </workspace> </service>
  • 20. introspective protocol <?xml version='1.0' encoding='UTF8'?> <service xmlns=quot;http://www.w3.org/2007/appquot; xmlns:atom=quot;http://www.w3.org/2005/Atomquot; > <workspace> <atom:titletype=quot;textquot;> AtomPub in the GTAC </atom:title> <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;> Gtac sessions </atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/schemequot; > <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> </categories> </collection> </workspace> </service>
  • 21.
  • 22. POST /sessions <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <app:edited>2007-12-13T18:30:02Z</app:edited> <content> testing atomPub servers </content> </entry>
  • 23. POST /sessions <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <app:edited>2007-12-13T18:30:02Z</app:edited> <content> testing atomPub servers </content> </entry> response.code == 201 response['Location'] == 'http://gtac.com/sessions/atomPub-testing'
  • 25. GET /sessions/atomPub-testing uri = Uri.parse response['Location'] Net::HTTP.start(uri.host, uri.port) do |http| @entry = http.request_get uri.path end or @doc = REXML::Document.new @feed link = REXML::XPath.first doc.root, 'entry/link[@rel=quot;editquot;]' uri = Uri.parse link Net::HTTP.start(uri.host, uri.port) do |http| @entry = http.request_get uri.path end or if response['Location'] == response['Content-Location'] @entry = response.body end
  • 26. GET /sessions/atomPub-testing @doc = REXML::Document.new @feed @entry = REXML::XPath.first doc.root, 'entry'
  • 28. PUT /sessions/atom-pub <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://localhost/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <app:edited>2007-12-13T18:30:02Z</app:edited> <content type=quot;htmlquot;> <div> testing <a href=quot;http://tools.ietf.org/html/rfc5023quot;>atomPub</a> servers </div> </content> </entry> response.code == 204
  • 30. DELETE /sessions/atom-pub uri = Uri.parse response['Location'] Net::HTTP.start(uri.host, uri.port) do |http| http.request Net::HTTP::Delete.new(uri.path) end response.code == 200
  • 31. what would happend with media?
  • 32. Media response.code == 201 response['Location'] == 'http://gtac.com/sessions/media.atom' <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/media.atomquot;/> <link rel=quot;edit-mediaquot; href=quot;http://gtac.com/sessions/mediaquot;/>
  • 33. testing the specification testing and best practices
  • 35. 405 Method not allowed
  • 37. other interesting codes 200 201 204 301 400 401 403 404 405 409 415 500
  • 40. building ids properly ‣ valid URI, rfc 2693 ‣ globally unique ‣ never change
  • 42. building ids properly “If you think that there's a good chance your URIs will change, you shouldn't use them for IDs. But, if you think that, you should also bloody well be looking for better software or hosting or whatever.” -- Tim Bray
  • 43. building ids properly “never mind the URI here’s my UUID” -- Bill de hÓra
  • 47. managing dates and sorting <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <created>2007-12-10T18:30:02Z</created> <updated>2007-12-13T18:30:02Z</updated> <published>2007-12-13T18:55:02Z</published> </entry>
  • 48. managing dates and sorting <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <created>2007-12-10T18:30:02Z</created> <updated>2007-12-13T18:30:02Z</updated> <published>2007-12-13T18:55:02Z</published> <app:edited>2007-12-13T18:40:02Z</app:edited> </entry>
  • 49. managing dates and sorting <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <feed xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot; xml:lang=quot;enquot;> <id>http://www.verbosemode.com/wp-app.php/posts</id> <updated>2007-11-13T22:07:43Z</updated> <entry> <updated>2008-06-04T22:07:43Z</updated> <published>2008-06-08T11:38:28Z</published> <app:edited>2008-07-13T22:07:43Z</app:edited> ... </entry> <entry> <updated>2007-11-13T22:07:43Z</updated> <published>2007-11-04T11:38:28Z</published> <app:edited>2007-11-13T22:07:43Z</app:edited> ... </entry>
  • 50. managing dates and sorting assert /(d{4})(?:-(d{2}))?(?:-(d{2}))?(?: ([Tt])?(?:(d{2}))?(?::(d{2}))?(?:: (d{2}))?(?:.(d{3}))?)?([Zz])?(?:([+-]) (d{2}):(d{2}))?/.match(date)[0]
  • 51. managing dates and sorting <updated>2007-12-13T18:30:02Z</updated> <updated>2007-12-13T18:30:02Z</updated> <updated>2007-12-13T18:30:02.25Z</updated> <updated>2007-12-13T18:30:02+01:00</updated> <updated>2007-12-13T18:30:02.25+01:00</updated>
  • 53. checking valid content def assert_valid_entry(entry) assert entry.id.absolute? assert_not_nil entry.title assert_not_nil entry.updated assert_not_nil entry.edited unless entry.content alternate = REXML::XPath.first entry, 'link[@rel=quot;alternatequot;]' assert_not_nil alternate else assert !entry.content.src.nil? or (Base64.decode64(entry.content.text) and !entry.summary.nil?) end end
  • 54. checking valid content <entry xmlns=quot;http://www.w3.org/2005/Atomquot;> <title type=quot;textquot;>unclean!</title> <summary type='xhtml'> <div xmlns='http://www.w3.org/1999/xhtml'> <p>hey</p> <script src='http://www.example.com/xxx' /> <script>alert('XXX')</script> <p id='x1' background=quot;javascript:alert('XSS')quot;>Hey</p> </div> </summary> <content type='xhtml'> <div xmlns='http://www.w3.org/1999/xhtml'> <p id='x2' style='whatever'>OK</p><object>No No No</object> <a href='/no-problemo'>aah</a> <a href='javascript:evil'>ouch</a> </div> </content>
  • 56. managing media <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>????</title> <summary>????</summary> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testing.atomquot;/> <link rel=quot;edit-mediaquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <app:edited>2007-12-13T18:30:02Z</app:edited> <content src=quot;http://gtac.com/managing-media.pngquot;/> </entry>
  • 57. managing media request['Slug'] == 'nice picture' <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>nice picture</title> <summary>nice picture</summary> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testing.atomquot;/> <link rel=quot;edit-mediaquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <app:edited>2007-12-13T18:30:02Z</app:edited> <content src=quot;http://gtac.com/managing-media.pngquot;/> </entry>
  • 59. categorizing resources <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;>Gtac sessions</atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/scheme/privacyquot;> <atom:category term=quot;publicquot;/> <atom:category term=quot;privatequot;/> <atom:category term=quot;friendsquot;/> <atom:category term=quot;familyquot;/> </categories> <categories scheme=quot;http://gtac.com/scheme/tagsquot;> <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> <atom:category term=quot;gtac08quot;/> <atom:category term=quot;atomquot;/> <atom:category term=quot;calaveraquot;/> </categories> </collection>
  • 60. categorizing resources <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <created>2007-12-10T18:30:02Z</created> <updated>2007-12-13T18:30:02Z</updated> <published>2007-12-13T18:55:02Z</published> <category scheme=quot;http://gtac.com/scheme/privacyquot; term=quot;TRYING TO ADD AN UNEXPECTED CATEGORYquot;/> </entry> response.code == 409
  • 61. categorizing resources <collection href=quot;/sessionsquot;> <atom:title type=quot;textquot;>Gtac sessions</atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed=quot;yesquot; scheme=quot;http://gtac.com/scheme/privacyquot;> <atom:category term=quot;publicquot;/> <atom:category term=quot;privatequot;/> <atom:category term=quot;friendsquot;/> <atom:category term=quot;familyquot;/> </categories> <categories scheme=quot;http://gtac.com/scheme/tagsquot;> <atom:category term=quot;testingquot;/> <atom:category term=quot;gtacquot;/> <atom:category term=quot;gtac08quot;/> <atom:category term=quot;atomquot;/> <atom:category term=quot;calaveraquot;/> </categories> </collection>
  • 63. extending atomPub my document is not valid!!! <?xml version='1.0' encoding='UTF8'?> <entry xmlns=quot;http://www.w3.org/2005/Atomquot; xmlns:app=quot;http://www.w3.org/2007/appquot;> <title>AtomPub testing session</title> <link rel=quot;editquot; href=quot;http://gtac.com/sessions/atomPub-testingquot;/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2007-12-13T18:30:02Z</updated> <georss:point>36.331445 -119.64592</georss:point> </entry>
  • 64. extending atomPub my document is not valid!!! def rnc_validate(schema, document) schemaError = StringWriter.new errorHandler = ErrorHandlerImpl.new(schemaError) properties = PropertyMapBuilder.new properties.put(ValidateProperty::ERROR_HANDLER, errorHandler) driver = ValidationDriver.new(properties.toPropertyMap, CompactSchemaReader.getInstance) driver.loadSchema(InputSource.new(StringReader.new(schema))) begin input = InputSource.new(StringReader.new(document)) error = schemaError.toString unless driver.validate(input) rescue org.xml.sax.SAXParseException error = $!.to_s.sub(/n.*$/, '') end error end
  • 65. putting it all together
  • 67. feed validator ‣ Atom, RSS, KML, OMPL... ‣ recognizes most standard namespaces ‣ runs locally as well: $ svn co http://feedvalidator.googlecode.com/svn/trunk/feedvalidator $ python src/demo.py http://code.google.com/p/feedvalidator/w/list
  • 69. AppClientTest tests basic aspects of atomPub $ svn co http://feedvalidator.googlecode.com/svn/trunk/apptestsuite/client/ validator/ validator $ python validator/appclienttest.py --output=results.html quot;http://bitworking.org/projects/apptestsite/app.cgi/ service/;service_documentquot; $ firefox results.html
  • 70. AppClientTest record and play it back!! $ python validator/appclienttest.py --record=./validator/rawtestdata/complete/ --html --output=test.html $ python validator/appclienttest.py --playback=./validator/rawtestdata/complete/ --html --output=test.html
  • 71. AppClientTest record and play it back!! $ tree validator/rawtestdata/complete/ validator/rawtestdata/complete/ |-- GET | `-- projects | `-- apptestsite | `-- app.cgi | |-- service | | |-- entry | | | |-- 1.file | | | |-- 1.file.2 | | | |-- 2.file | | | |-- 2.file.2 | | | |-- 2.file.3
  • 72. AppClientTest html output with links to the specification
  • 73. AtomPub Test Client ms windows desktop client
  • 74. The Atom Publishing Exerciser
  • 75. The Atom Protocol Excerciser rubygem library with more than 50 test cases $ svn co http://ape.rubyforge.org/svn/trunk ape $ gem install ape command line tasks $ rake -T rake ape:go:atom[uri,username,password] rake ape:go:html[uri,username,password] rake ape:go:text[uri,username,password]
  • 76. The Atom Protocol Excerciser inbuilt web server
  • 77. The Atom Protocol Excerciser completely extensible!! ‣ authentication: basic_auth, wsse, googleLogin ‣ formats: text, html, atom ‣ validators
  • 79. questions? ‣ Blog: http://thinkincode.net ‣ Email: calavera@apache.org ‣ Resources: ‣ RFC 5023: http://www.ietf.org/rfc/rfc5023.txt ‣ RFC 4287: http://www.ietf.org/rfc/rfc4287.txt ‣ RFC 2616: http://www.ietf.org/rfc/rfc2616.txt ‣ RFC 2693: http://www.ietf.org/rfc/rfc2693.txt ‣ Apache Abdera: http://incubator.apache.org/abdera ‣ Feed validator: http://feedvalidator.org ‣ AppClientTest: http://code.google.com/p/feedvalidator/wiki/AppClientTest ‣ AtomPub test client: http://www.witha.jp/eXeries/software/ ‣ The APE: http://rubyforge.org/projects/ape
  • 80. photos ‣ http://flickr.com/photos/visualpanic/2240763525/ ‣ http://flickr.com/photos/edgeplot/1529475806/ ‣ http://flickr.com/photos/perstephanie/2806654855/ ‣ http://flickr.com/photos/giornaletecnologico/1566587705/ ‣ http://flickr.com/photos/visualpanic/1474644715/ ‣ http://flickr.com/photos/javi_co/2516310892/ ‣ http://flickr.com/photos/suttonhoo22/2512983749/ ‣ http://flickr.com/photos/xanboozled/784164182/ ‣ http://flickr.com/photos/baloncestorrelavega/2736961248/ ‣ http://flickr.com/photos/jork85/1776795805/ ‣ http://flickr.com/photos/jessefriedman/1435220149/ ‣ http://flickr.com/photos/apelad/304197126/ ‣ http://flickr.com/photos/apelad/304194299/ ‣ http://flickr.com/photos/dw/827997520/ ‣ http://flickr.com/photos/lapidim/59044209/ ‣ http://flickr.com/photos/visualpanic/365605949/ ‣ http://flickr.com/photos/visualpanic/2261768075/ ‣ http://flickr.com/photos/drift-words/99645/ ‣ http://flickr.com/photos/prawnpie/369727578/ ‣ http://flickr.com/photos/laydros/2877137537/ ‣ http://flickr.com/photos/bretarnett/75243850/ ‣ http://flickr.com/photos/wcouch/2091338695/