• No results found

Identifying the Resource and Representation

In document Ajax Patterns And Best Practices pdf (Page 147-150)

Taking a closer look at the URL http://mydomain.com/books/[ISBN], let’s work through how it would be implemented. The URL refers to a specific book with the identified ISBN number. When the URL is sent to an HTTP server, a response is generated. The problem is determining which content the server should send to the client. Separating the resource from the represen- tation means that a single URL will have separate representations. The representation that is sent depends on the value of the HTTP Accept-* header, but that header need not be the only one. As was just mentioned, the user using a query variable could specify the representation. More about other HTTP headers will be discussed shortly. For now, let’s focus on the Accept

HTTP header and consider the following HTTP conversation that returns some content. Request:

GET /books/3791330942 HTTP/1.1 Host: 192.168.1.242:8100

User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; ➥

en-US; rv:1.7.8) Gecko/20050511 Accept: text/xml,application/xml,application/xhtml+xml, ➥ text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Response: HTTP/1.1 200 OK

Date: Sun, 21 Aug 2005 14:51:40 GMT

Server: Apache/2.0.53 (Ubuntu) PHP/4.3.10-10ubuntu4 Last-Modified: Wed, 11 May 2005 17:43:45 GMT ETag: "41419c-45-438fd340"

Accept-Ranges: bytes Content-Length: 69

Keep-Alive: timeout=15, max=100 Connection: Keep-Alive

Content-Type: text/html; charset=UTF-8

The request is an HTTP GET, which means the HTTP server needs to retrieve the data asso- ciated with the resource. The operation becomes specific due to the request-provided HTTP headers Accept, Accept-Language, Accept-Encoding, and AcceptCharset. These HTTP headers are accepted by the HTTP server and indicate what content to send.

Focusing on the HTTP header Accept, you can see that the values are a series of MIME- encoded identifiers that the client can accept and process. The order and type of the identifier are important because they specify the priority of the content that the client wants to receive from the server. The logic is to send the best content available that has the best priority defined by the client. This, for example, forces the server to send HTML content before plain text content. As per the HTTP specification, the priority of the example request-provided MIME types is as follows: 1. application/xhtml+xml 2. text/xml 3. application/xml 4. image/png 5. text/html;q=0.9 6. text/plain;q=0.8 7. */*;q=0.5

The ordering of the identifiers depends on the identifier specialization and its q value. When a MIME-type identifier has no q value, it means a default value of 1.0. When there is a q value, it means to lower the priority of the MIME-type identifier to the value specified by the q value. Identifier specialization occurs when one identifier is a higher priority because the content specified is more specific than the other identifier. In the list of priorities, the identifier text/ xml is more specific than */* because */* means everything. Additionally, text/xml is more specific than text/*, and hence text/xml is a higher priority.

What you should notice is that the first MIME identifier from the HTTP conversation is

text/xml, and the second is application/xml. Yet in the priority ordering, the first MIME iden- tifier is application/xhtml-xml. This is an assumption I made after having read the HTTP and MIME specifications,2 but I feel it’s a bug that happens to be correct.

To understand why this bug happens to be correct, the example request needs to be dissected. The MIME-type identifiers application/xml, text/xml, and application/xhtml-xml are consid- ered specific, and each has a q value of 1. If the order of the MIME types as issued by the browser is followed, it means that the browser prefers receiving XML content to HTML or XHTML content. From the specifications, application/xml and text/xml MIME types contain XML content, although the XML content could be XHTML content. Reading the specification solves the problem because it indicates that a more specific MIME type is ordered before a less specific MIME type. This means application/xhtml-xml is ordered before application/xml and text/xml because

application/xhtml-xml is specifically formatted XML.

Having solved this bug (which could be considered an interesting feature) and having sent the proper representation, figuring out what to send with respect to the Accept HTTP header does not get any better. Following is another HTTP request that asks for some content.

Request:

GET /books/3791330942 HTTP/1.1 Accept: */*

Accept-Language: en-ca

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; ➥

Windows NT 5.1; SV1; .NET CLR 2.0.50215; .NET CLR 1.1.4322) Connection: Keep-Alive

Some browsers send the Accept type identifier */*, which essentially means, “Send me whatever you’ve got; I will accept it.” Such a request is extremely unhelpful and makes it diffi- cult to implement the separation of the resource from the representation. The solution to this problem is to define a default representation for the identifier */*. It’s not an ideal solution, but a solution created from the necessity to send something. A good default is HTML because those clients that send */* are most likely HTML-based web browsers.

Knowing the preferences of the client, and combining those preferences with the URL, it is possible to send a representation. The decisions are encapsulated into a component that routes the content. The component when called can contain the logic to do one of two things: send the appropriate content, or rewrite the URL that will send the appropriate content. The preferred approach is to rewrite the URL to something that will send the appropriate content. So, for example, if a web browser is interested in the document /book, the representation is

/book/[document].html. If an XML-based REST client is interested in the content /book, the representation is /book/[content].xml.

The URL rewrite approach is used for the following reasons:

• Content editors such as Microsoft FrontPage, Macromedia Dreamweaver, or Altova XMLSpy require a specific URL that can be used to edit content. Content editors are not able to edit different representations associated with a single URL.

• A generic URL can be bookmarked, but a redirection to a specific URL can be downloaded.

• URLs can be dynamically routed to any content, which makes it possible to include application versioning capabilities.

The result is that the routing component will never know the details of the content sent to the client. The routing component knows only the URL of the content. The Accept header was illustrated as a way to provide a cue on how to redirect the request, but other HTTP headers can also be used. In the example HTTP headers, Accept-Language indicates the language that the content should be returned in. The routing component needs to consider both HTTP headers when rewriting the URL. The result could be HTML pages in multiple languages, XML content in a subset of languages and encodings, and so on. The routing component manages all the decisions and rewrites the URL to the appropriate representation. This frees the representation developer from having to figure out what content to send.

Now that you have read about the architecture of the Permutations pattern, it should be obvious why the pattern is called what it is. The idea is that a resource is transformed into a set of representations, and the client can choose one of those representations. The remaining part of this chapter is about implementing the Permutations pattern.

Implementation

In the implementation of the Permutations pattern, there are two concerns: associating a representation with a resource, and authorizing a user to access a resource or representation. The implementation of the two concerns requires the creation of a URL rewriter component. The purpose of the URL rewriter component is to inspect the request and decide which content should be generated.

In document Ajax Patterns And Best Practices pdf (Page 147-150)