You are previewing RESTful Web Services.

RESTful Web Services

Cover of RESTful Web Services by Leonard Richardson... Published by O'Reilly Media, Inc.
  1. RESTful Web Services
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Foreword
    4. Preface
      1. The Web Is Simple
      2. Big Web Services Are Not Simple
      3. The Story of the REST
      4. Reuniting the Webs
      5. What’s in This Book?
      6. Administrative Notes
      7. Conventions Used in This Book
      8. Using Code Examples
      9. Safari® Enabled
      10. How to Contact Us
      11. Acknowledgments
    5. 1. The Programmable Web and Its Inhabitants
      1. Kinds of Things on the Programmable Web
      2. HTTP: Documents in Envelopes
      3. Method Information
      4. Scoping Information
      5. The Competing Architectures
      6. Technologies on the Programmable Web
      7. Leftover Terminology
    6. 2. Writing Web Service Clients
      1. Web Services Are Web Sites
      2. The Sample Application
      3. Making the Request: HTTP Libraries
      4. Processing the Response: XML Parsers
      5. JSON Parsers: Handling Serialized Data
      6. Clients Made Easy with WADL
    7. 3. What Makes RESTful Services Different?
      1. Introducing the Simple Storage Service
      2. Object-Oriented Design of S3
      3. Resources
      4. HTTP Response Codes
      5. An S3 Client
      6. Request Signing and Access Control
      7. Using the S3 Client Library
      8. Clients Made Transparent with ActiveResource
      9. Parting Words
    8. 4. The Resource-Oriented Architecture
      1. Resource-Oriented What Now?
      2. What’s a Resource?
      3. URIs
      4. Addressability
      5. Statelessness
      6. Representations
      7. Links and Connectedness
      8. The Uniform Interface
      9. That’s It!
    9. 5. Designing Read-Only Resource-Oriented Services
      1. Resource Design
      2. Turning Requirements Into Read-Only Resources
      3. Figure Out the Data Set
      4. Split the Data Set into Resources
      5. Name the Resources
      6. Design Your Representations
      7. Link the Resources to Each Other
      8. The HTTP Response
      9. Conclusion
    10. 6. Designing Read/Write Resource-Oriented Services
      1. User Accounts as Resources
      2. Custom Places
      3. A Look Back at the Map Service
    11. 7. A Service Implementation
      1. A Social Bookmarking Web Service
      2. Figuring Out the Data Set
      3. Resource Design
      4. Design the Representation(s) Accepted from the Client
      5. Design the Representation(s) Served to the Client
      6. Connect Resources to Each Other
      7. What’s Supposed to Happen?
      8. What Might Go Wrong?
      9. Controller Code
      10. Model Code
      11. What Does the Client Need to Know?
    12. 8. REST and ROA Best Practices
      1. Resource-Oriented Basics
      2. The Generic ROA Procedure
      3. Addressability
      4. State and Statelessness
      5. Connectedness
      6. The Uniform Interface
      7. This Stuff Matters
      8. Resource Design
      9. URI Design
      10. Outgoing Representations
      11. Incoming Representations
      12. Service Versioning
      13. Permanent URIs Versus Readable URIs
      14. Standard Features of HTTP
      15. Faking PUT and DELETE
      16. The Trouble with Cookies
      17. Why Should a User Trust the HTTP Client?
    13. 9. The Building Blocks of Services
      1. Representation Formats
      2. Prepackaged Control Flows
      3. Hypermedia Technologies
    14. 10. The Resource-Oriented Architecture Versus Big Web Services
      1. What Problems Are Big Web Services Trying to Solve?
      2. SOAP
      3. WSDL
      4. UDDI
      5. Security
      6. Reliable Messaging
      7. Transactions
      8. BPEL, ESB, and SOA
      9. Conclusion
    15. 11. Ajax Applications as REST Clients
      1. From AJAX to Ajax
      2. The Ajax Architecture
      3. A Example
      4. The Advantages of Ajax
      5. The Disadvantages of Ajax
      6. REST Goes Better
      7. Making the Request
      8. Handling the Response
      9. JSON
      10. Don’t Bogart the Benefits of REST
      11. Cross-Browser Issues and Ajax Libraries
      12. Subverting the Browser Security Model
    16. 12. Frameworks for RESTful Services
      1. Ruby on Rails
      2. Restlet
      3. Django
    17. A. Some Resources for REST and Some RESTful Resources
      1. Standards and Guides
      2. Services You Can Use
    18. B. The HTTP Response Code Top 42
      1. Three to Seven Status Codes: The Bare Minimum
      2. 1xx: Meta
      3. 2xx: Success
      4. 3xx: Redirection
      5. 4xx: Client-Side Error
      6. 5xx: Server-Side Error
    19. C. The HTTP Header Top Infinity
      1. Standard Headers
      2. Nonstandard Headers
    20. Index
    21. About the Authors
    22. Colophon
    23. SPECIAL OFFER: Upgrade this ebook with O’Reilly

Figuring Out the Data Set

Because I’m basing my service on an existing one, it’s fairly easy to figure out the parameters of the data set. If what follows is confusing, feel free to flip back to The Sample Application” in Chapter 2 for an overview of

The site has four main kinds of data: user accounts, bookmarks ( calls them “posts”), tags (short strings that act as metadata for bookmarks), and bundles (collections of tags for a user). The web site and the web service track the same data set.

Unlike an S3 bucket, or a user account on my map service, a user account is not just a named list of subordinate resources. It’s got state of its own. A account has a username and password, but it’s supposed to correspond to a particular person, and it also tracks that person’s full name and email address. A user account also has a list of subordinate resources: the user’s bookmarks. All this state can be fetched and manipulated through HTTP.

A bookmark belongs to a user and has six pieces of state: a URI, a short and a long description, a timestamp, a collection of tags, and a flag that says whether or not it’s public (the previous chapter’s “custom place” resource has a similar flag). The client is in charge of specifying all of this information for each bookmark, though the URI and the short description are the only required pieces of state.

The URIs in users’ bookmarks are the most interesting part of the data set. When you put a bunch of peoples’ bookmarks together, you find that the URIs have emergent properties. On these properties include newness, a measure of how recently someone bookmarked a particular URI; “popularity,” a measure of how many people have bookmarked that URI; and the “tag cloud,” a generated vocabulary for the URI, based on which tags people tend to use to describe the URI. The web site also exposes a recommendation engine that relates URIs to each other, using a secret algorithm.

I’m not going to do much with the emergent properties of URIs, properties that account for much of’s behind-the-scenes code. My implemented service will have a notion of newness but it won’t have popularity, tag clouds, or recommendation algorithms. This is just so I can keep this book down to a manageable size instead of turning it into a book about recommendation algorithms.

Tags have only one piece of state: their name. They only exist in relation to bookmarks—and bundles, which I haven’t described yet. A bundle is a user’s decision to group particular tags together. A user with tags “recipes,” “restaurants,” and “food,” might group those tags into a bundle called “gustation.” I’ll show the RESTful design of bundles, just for completeness, but I won’t be implementing them when it comes time to write code.

At this point I know enough about the data set to create the database schema. I create an empty database called bookmarks_development in my MySQL installation, and put this data in the file db/migrate/001_initial_schema.rb, shown in Example 7-1.

Example 7-1. The bookmark database schema as a Rails migration

class InitialSchema < ActiveRecord::Migration

  # Create the database tables on a Rails migration.
  def self.up
    # The 'users' table, tracking four items of state 
    # plus a unique ID.
    create_table :users, :force => true do |t|
      t.column :user_id, :string
      t.column :name, :string
      t.column :full_name, :string
      t.column :email, :string
      t.column :password, :string

    # The 'bookmarks' table, tracking six items of state,
    # plus a derivative field and a unique ID.
    create_table :bookmarks, :force => true do |t|
      t.column :bookmark_id, :string
      t.column :uri, :string
      t.column :uri_hash, :string   # A hash of the URI.
                                    # See book text below.
      t.column :short_description, :string
      t.column :long_description, :text
      t.column :timestamp, :datetime
      t.column :public, :boolean

    # This join table reflects the fact that bookmarks are subordinate
    # resources to users.
    create_table :user_bookmarks, :force => true do |t|
      t.column :user_id, :integer
      t.column :bookmark_id, :integer

    # These two are standard tables defined by the acts_as_taggable
    # plugin, of which more later. This one defines tags.
    create_table :tags do |t|
      t.column :name, :string

    # This one defines the relationship between tags and the things
    # tagged--in this case, bookmarks.
    create_table :taggings do |t|
      t.column :tag_id, :integer
      t.column :taggable_id, :integer
      t.column :taggable_type, :string

    # Four indexes that capture the ways I plan to search the
    # database.
    add_index :users, :name
    add_index :bookmarks, :uri_hash
    add_index :tags, :name
    add_index :taggings, [:tag_id, :taggable_id, :taggable_type]
  # Drop the database tables on a Rails reverse migration.
  def self.down
    [:users, :bookmarks, :tags, :user_bookmarks, :taggings].each do |t|
      drop_table t

I’ve used Ruby code to describe five database tables and four indexes. I create the corresponding database schema by running this command:

$ rake db:migrate

The best content for your career. Discover unlimited learning on demand for around $1/day.