Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
143023864X_HT5.pdf
Скачиваний:
8
Добавлен:
21.02.2016
Размер:
7.98 Mб
Скачать

CHAPTER 6 USING THE COMMUNICATION APIS

127.0.0.1 chat.example.net

127.0.0.1 portal.example.com

Note You must restart your browser after modifying the host file to ensure that the DNS entries take effect.

2.Install Python 2, which includes the lightweight SimpleHTTPServer web server.

3.Navigate to the directory that contains the two example files (postMessageParent.html and postMessageWidget.html).

4.Start Python as follows:

python -m SimpleHTTPServer 9999

5.Open a browser and navigate to http://portal.example.com:9999/postMessagePortal.html. You should now see the page shown in Figure 6-4.

XMLHttpRequest Level 2

XMLHttpRequest is the API that made Ajax possible. There are many books about XMLHttpRequest and Ajax. You can read more about XMLHttpRequest programming in John Resig’s Pro JavaScript Techniques, (Apress, 2006).

XMLHttpRequest Level 2—the new version of XMLHttpRequest—has been significantly enhanced. In this chapter, we will be covering the improvements introduced in XMLHttpRequest Level 2. These improvements are centered on the following areas:

Cross-origin XMLHttpRequests

Progress events

Binary Data

Cross-Origin XMLHttpRequest

In the past, XMLHttpRequest was limited to same-origin communication. XMLHttpRequest Level 2 allows for cross-origin XMLHttpRequests using Cross Origin Resource Sharing (CORS), which uses the origin concept discussed in the earlier Cross Document Messaging section.

Cross-origin HTTP requests have an Origin header. This header provides the server with the request’s origin. This header is protected by the browser and cannot be changed from application code. In essence, it is the network equivalent of the origin property found on message events used in Cross Document Messaging. The origin header differs from the older referer [sic] header in that the referer is a complete URL including the path. Because the path may contain sensitive information, the referer is sometimes not sent by browsers attempting to protect user privacy. However, the browser will always send the required Origin headers when necessary.

Using cross-origin XMLHttpRequest, you can build web applications that use services hosted on different origins. For example, if you wanted to host a web application that used static content from one

146

CHAPTER 6 USING THE COMMUNICATION APIS

origin and Ajax services from another, you could use cross-origin XMLHttpRequest to communicate between the two. Without cross-origin XMLHttpRequest, you would be limited to same-origin communication. This would constrain your deployment options. For example, you might have to deploy the web application on a single domain or set up a subdomain.

As shown in Figure 6-5, cross-origin XMLHttpRequest allows you to aggregate content from different origins on the client side. Additionally, you can access secured content with the user’s credentials if the target server allows it, providing users with direct access to personalized data. Serverside aggregation, on the other hand, forces all content to be funneled through a single server-side infrastructure, which can create a bottleneck.

Figure 6-5. Difference between client-side and server-side aggregation

The CORS specification dictates that, for sensitive actions—for example, a request with credentials, or a request other than GET or POST—an OPTIONS preflight request must be sent to the server by the

147

CHAPTER 6 USING THE COMMUNICATION APIS

browser to see whether the action is supported and allowed. This means that successful communication may require a CORS-capable server. Listings 6-5 and 6-6 show the HTTP headers involved in a crossorigin exchange between a page hosted on www.example.com and a service hosted on www.example.net.

Listing 6-5. Example Request Headers

POST /main HTTP/1.1 Host: www.example.net

User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090910 Ubuntu/9.04 (jaunty) Shiretoko/3.5.3

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 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

Referer: http://www.example.com/ Origin: http://www.example.com Pragma: no-cache

Cache-Control: no-cache Content-Length: 0

Listing 6-6. Example Response Headers

HTTP/1.1 201 Created

Transfer-Encoding: chunked

Server: Kaazing Gateway

Date: Mon, 02 Nov 2009 06:55:08 GMT

Content-Type: text/plain

Access-Control-Allow-Origin: http://www.example.com

Access-Control-Allow-Credentials: true

Progress Events

One of the most important API improvements in XMLHttpRequest has been the changes related to progressive responses. In the previous version of XMLHttpRequest, there was only a single readystatechange event. On top of that, it was inconsistently implemented across browsers. For example, readyState 3 (progress) never fires in Internet Explorer. Furthermore, the readyState change event lacked a way to communicate upload progress. Implementing an upload progress bar was not a trivial task and involved server-side participation.

XMLHttpRequest Level 2 introduces progress events with meaningful names. Table 6-2 shows the new progress event names. You can listen for each of these events by setting a callback function for the event handler attribute. For example, when the loadstart event fires, the callback for the onloadstart property is called.

148

CHAPTER 6 USING THE COMMUNICATION APIS

Table 6-1. New XMLHttpRequest Level 2 Progress Event Names

Progress Event Name

loadstart

progress

abort

error

load

loadend

The old readyState property and readystatechange events will be retained for backward compatibility.

“Seemingly Arbitrary” Times

In the XMLHttpRequest Level 2 specification’s description for the readystatechange event (maintained for backward compatibility), the readyState attribute is described as changing at, get this, “some seemingly arbitrary times for historical reasons.

Browser Support for HTML5 XMLHttpRequest Level 2

HTML5 XMLHttpRequest is already supported in many browsers at the time of this writing. Due to the varying levels of support, it is a good idea to first test if HTML5 XMLHttpRequest is supported, before you use these elements. The section “Checking for Browser Support” later in this chapter will show you how you can programmatically check for browser support.

Using the XMLHttpRequest API

In this section, we’ll explore the use of the XMLHttpRequest in more detail. For the sake of illustration, we’ve created a simple HTML page—crossOriginUpload.html. The sample code for the following examples is located in the code/communication folder.

Checking for Browser Support

Before you try to use XMLHttpRequest Level 2 functionality—such as cross-origin support—it is a good idea to check if it is supported. You can do this by checking whether the new withCredentials property is available on an XMLHttpRequest object as shown in Listing 6-7.

149

CHAPTER 6 USING THE COMMUNICATION APIS

Listing 6-7. Checking if Cross-Origin Support Is Available in XMLHttpRequest

var xhr = new XMLHttpRequest()

if (typeof xhr.withCredentials === undefined) { document.getElementById("support").innerHTML =

"Your browser <strong>does not</strong> support cross-origin XMLHttpRequest";

} else { document.getElementById("support").innerHTML =

"Your browser <strong>does</strong>support cross-origin XMLHttpRequest";

}

Making Cross-Origin Requests

To make a cross-origin XMLHttpRequest, you must first create a new XMLHttpRequest object, as shown in the following example.

var crossOriginRequest = new XMLHttpRequest()

Next, make the cross-origin XMLHttpRequest by specifying an address on a different origin as shown in the following example.

crossOriginRequest.open("GET", "http://www.example.net/stockfeed", true);

Make sure, you listen for errors. There are many reasons why this request might not succeed. For example, network failure, access denied, and lack of CORS support on the target server.

WHY NOT JSONP?

Frank says: “One common way to fetch data from another origin is JSONP (JSON with padding). JSONP involves creating a script tag with the URL of a JSON resource. The URL has a query parameter containing the name of a function to invoke when the script loads. It is up to the remote server to wrap the JSON data with a call to the named function. This has serious security implications! When you use JSONP, you must completely trust the service providing the data. A malicious script could take over your application.

With XMLHttpRequest (XHR) and CORS, you receive data instead of code, which you can parse safely. It’s far safer than evaluating external input.”

Using Progress Events

Instead of numerical states representing different stages of the request and response, XMLHttpRequest Level 2 provides named progress events. You can listen for each of these events by setting a callback function for the event handler attribute.

Listing 6-8 shows how callback functions are used to handle progress events. Progress events have fields for the total amount of data to transfer, the amount that has already transferred, and a Boolean value indicating whether the total is known (it may not be in the case of streaming HTTP). XMLHttpRequest.upload dispatches events with the same fields.

150