Title:
Empowering your site with HTTP Requests
Increasing speed without loading the whole page
Byline:
by Martin Fasani
Deck:
The XML HTTP Request was implemented by Microsoft in internet explorer 5 to provide client-side
protocol support for communication with HTTP servers. Later on the developers of the Mozilla project
implemented a native version on Mozilla 1.0. Thankfully they modeled their implementation with the same
methods of the MS's one so aside for the initial creation of the object the rest of the code will be the same for
both.
Requirements:
Author: please enter your requirements below.
PHP:
4.x.x
O/S:
Linux - Windows
Other software:
Useful / Related Links
http://www.mozilla.org/xmlextras/
http://sarissa.sourceforge.net/doc/
Author bio:
Martin works for telecommunications in Spain delivering statistic reports and building
extranets for clients. He is interested on social software and can be contacted through his
website http://movil.be
Article body:
Actually there is a growing support for this HTTP request method so almost all the browsers
support it or are moving in that direction. Internet Explorer 5 and above on Windows,
Konqueror, Safari on Mac OS-X and Mozilla on all platforms handles HTTP requests,
Opera 7.6preview 1 also now features the object.
Why do we need this technology ?
Besides using frames there is no way in standard html to reload a part of the page
getting information from the server side. Using the XML HTTP Request method
(HTTPREQ from now on) makes this fast and elegant. It's a object that runs inside the
client browser allowing you to make requests without reloading the page. While the object
is called the XML HTTP Request object it is not limited to being used with XML so it can
request or send any type of document. Like Apple comments, it's a Cool combo, since web
developers wanted a clean way to maintain connection with the server so they can make
transactions in the background bringing newly updated data in the page without using frames
or java applets. Live examples about this request method in use are Google Suggest
(http://www.google.com/webhp?complete=1&hl=en ) and another one is the now
popular Gmail. Many people wondered why it had those impressive page-loading speeds or
how it keeps state of changes without refreshing the page. The magic behind that is the
HTTPREQ object.
When I first started writing I was wondering that about the fact that is client side object,so
why I would write an article for php|arch ?. They are two the reasons that push me to keep
on, the first one is that in standard environment you've normal security restrictions that
avoid making this type of request outside the domain they are running, the second one is
that it can be handy to write a php class to make this without needing to type client side code
or at least, keeping it to the minimum expression. The catch to build interfaces using the
HTTPREQ methods is that you need to combine both worlds the client scripting with the
server side. Being the client the one that will take care of sending the request and after
getting the response the one that will reflect the changes on the page.
What can be done ?
HTTPREQ is flexible, and that means that you can make different types of requests
through it:
* A Simple Request gets a file on the server dynamically
* Sending a SOAP/ REST request
* A Head Request returns the HTTP headers of a page
Head requests are very useful to check when a log file or any other file gets updated on your
server getting the last-modified header.
Basically you can do any standard HTTP request using GET or POST the only
difference is that the response is going to be returned to the same page and handled by this
HTTPREQ object. Putting it all this together you can do lots of little things which when
added up can make certain pages and forms work faster. This makes HTTPREQ an
extremely versatile system for making user friendly administration control-panels. You can
grab from the server the information that you need and change that specific part of page
without refreshing the hole information. Like this you make an improvement over speed,
sending less amount of information between server and client, the essential information you
need and not the entire fields of the form/html.
Considering that being an object on the client browser is running on a "sandbox" it adopts
the same domain security policies of typical JavaScript activity. That will be no problem since
we will execute php on our domain to make the external requests. This opens the way to
make the hierarchical forms items items as Country, Province and City get the content
elements from the server, without needing to charge it all on one page or reloading the hole
form just get the information for the next select box. New messages on a BBS forum or any
other multi user system will get also the goodies of this silent requests.
While I'm going to focus this article in doing things with the object and php it's worth to
mention that I will try to keep the javascript to the minimum expression just to handle the
object and bringing back the results. The easiest thing then is building a class to pass the
properties and methods we are going to use so it creates all the <script> client side for us.
So after this small introduction and the basic client side code we will be using our handy
class to make the client code.
The complexity get's in the way when you need enhanced forms because you are making this
request and getting response in the client side, thus there is a need to interpret the response
or either writing the response raw inside an HTML container like a DIV tag. But most of the
time you will need to use this to change state or fill select boxes, checkboxes or other form
elements, so there is some additional client side code to play with.
While I'll explain this as simple as possible a basic understanding of JavaScript and
html will be useful to follow me completely.
Increasing user experience, keeping form state and scrollbars in place
When I think about increasing the user experience the first that comes to my mind is
making your webpage's and forms run with the most user friendly interface and fast as
possible. And here is where HTTPREQ comes into place as a transparent object that sits on
your page making requests without refreshing the page. In a fast though, this allows having
long vertical lists updating content and checkboxes at real time, on a "create new account" to
alert that your nickname is already existing before submitting all data, checking for new
messages on a email client and adding them on the fly, showing alerts in administration
panels. And the list goes up to your imagination creating web interfaces.
At the end, after mastering the HTTPREQ Method you will start thinking "what else
can I bring back from the server?"
Creating the object on the client side
We will first see the client side of the code then we will make a simple class to generate this client
side with php. This is a practical view of the object with main methods and properties exposed in
this article, if you need to do a specific task there is http://www.mozilla.org/xmlextras .
To cope with all versions of explorer above 5.0 and all the rest of the browsers supporting
the object we will write the object creator in a text file httpreq.js :
HTTPREQ = false;
/*@cc_on @*/ /*@if (@_jscript_version >= 5)
var ieversion = ["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
for(var i=0; !HTTPREQ && i<ieversion.length; i++) {
try{ HTTPREQ = new ActiveXObject(ieversion[i]); } catch(e)
{ HTTPREQ = false; } } @end @*/
if (!HTTPREQ && typeof XMLHttpRequest!='undefined') {
HTTPREQ = new XMLHttpRequest(); // [mozilla/safari/opera]
}
After this, we can have our "hello world" up and running:
<script src="httpreq.js"></script>
<script language="javascript">
HTTPREQ.open("GET", "http://localhost/hello.txt", true);
HTTPREQ.onreadystatechange=function() { if (HTTPREQ.readyState==4) { alert (HTTPREQ.responseText)} };
HTTPREQ.send(null);
</script>
After creating the object, the open() and send() methods are the ones you'll likely use most:
HTTPREQ.open("method", "URL"[, asyncFlag])
method specifies if you use GET / POST
asyncFlag (boolean)
true: async mode This is the preferred method to use in a web page
false: sync mode Client-Server connection is maintained (the UI will while lock until
request is being made.)
It 's recommended to use the ASYNC mode to prevent freezing the browser UI until
you get the response. ASYNC is the preferred method to use in a webpage since it prevents
locking and avoids high response times from the server. There is really no need of using
SYNC mode in a website, or at least I didn't found the necessity of using it as it freezes until
the result comes back to the browser making it work in a one time request basis.
HTTPREQ.send(variable)
Sends the HTTPREQ to the server and receives a response.
Optionally if you need to force a stream to be treated and parsed as text/xml, after calling
open , you can also use the setRequestHeader :
setRequestHeader ( in string header, in string value )
Then onreadystatechange will specify the event handler that is called when the state of the
request changes, which will let you grab the value of readyState property which represents
the state of the request:
readyState== 0 Object not initiated
readyState== 1 Loading, object created, send method still not initiated
readyState== 2 Send method called, but nothing available yet
readyState== 3 Some data received, response is not fully available
readyState== 4 Completed, at this point you can read the result of the request.
The basic logic to use the HTTPREQ :
1.The page is loaded
2. The browser initializes the HTTPREQ object
3. The onload function is called (or any other through user interaction)
4. A request is performed
5. When the request is completed (readyState ==4), a function is called
6. Based on response you can be add content to an html container or you can use to
update/change any other element of the page.
To keep compatibility with the most broad range of browsers it's recommended to use
the methods and properties of Mozilla which are listed at:
http://unstable.elemental.com/mozilla/build/latest/mozilla/extensions/dox/interfac
ensIXMLHttpRequest.html
Integrating with your server side php code
Basically you create your php normally receiving the GET or POST parameters. Then
you request the page with the XMLREQ Method described before. After doing the work in
php you return response that you interpret again in the client side.
Making it more visual:
Client -> XMLREQ -> Server php -> Response -> Client again interpreting response and
publishing results.
Now let's go back to business and let's create a handy class to generate javascript code used
to make some simple requests. I hope that this start will be useful to extend the class to
another uses, or just to copy and paste the generated code to customize and add additional
features. The mission of this class will be to create client side code to make basic requests in
4 lines of code:
<?
require("classhttpreq.php");
$req1 = new httpreq('req1');
$req1->httpdorequest('GET','helloworld.txt');
$req1->httpcreate();
?>
We will create some public methods that build chunks of javascript to generate the request
and when done will publish the response in <DIV> html containers:
new httpreq($obj)
Httpreq is the constructor that will check browser type and create the corresponding
XMLHttpRequest() object.
send(data , [type: file / url / string by default], [cleanwhitespace: true by default])
Optional, to send the body of the message with the request. If is not set, will send an empty
string to fire the request. If you are using GET to send the request you can skip this because
the values can be sent as a querystring in the URL of the request.
httpdorequest($method,$url,$async=true)
Will open the request, if set, sending the body of the message. Creates a JS function called:
Function httpdo[$this->obj]() in the example above would be httpdoreq1() function.
Additionally makes the event handler function which is fired each time that readyState
property changes and names the function httpresponse[$this->obj]. This is the function that
will display "Loading…" and the response when the request is completed.
Up to here and playing a bit with the class to generate the Javascript code it doesn't look
difficult. But you can scratch your head thinking how this request filling DIV tags can help
me out to build something usefull ? This is build as a demo to show how the basic
functioning works keeping the client side to the minimum expression. Of course, it's meant
that you can pick this up and build more methods to handle any other type of content,
update forms filling select boxes and such, or validating fields on the fly. It's very difficult to
give specific examples because it depends exactly on what you need to do with your requests
and how you need content updated will change the way to build this requests. But first
things first, as Stephen Covey would say, you need to define very well where to place the
request and what it will do to improve the speed or add
About security and drawbacks
By default browsers do not allow any kind of client script do cross domain requests
for security reasons. If you put your page and the data source to the same web server all
examples will should work both in IE and Mozilla/Firefox.
So in case you want to make request over different domains what you should do is
build a proxy in php that do the work dropping the result locally.
The security level should be the same used in any other web based development. One
issue is that actually HTTPREQ is not sending referer headers in all the browsers so it 's not
possible to validate what domain is making the request (e.g. IE does,Mozilla does not). If
you are working on a administration site that handles sensible information is very important
to work using authentication and sessions. One interesting thing is that you can use session
across the main page and the page being requested so it should be no problem to validate
users. On the other side, making a public service that returns information to publish in
another site, it should be essential to do data filtering to make sure that the request is valid.
(http://phpsec.org is a good resource to read about security )
In the usability side it's always recommended to provide a degradated page with no
HTTPREQ's just in case they are using a browser that does not support this object. If
accessibility is important in your project take in account that the browser reading tools could
not get along very well with this dynamic html remix. I hope this article proves that making
requests with this object is not utterly difficult and that it's possibly to start using it right
away as it's getting accepted by most of the browsers out there. There is the object
exposed, it's been there for a couple of years now, and it's a good time to extend this on and
start integrating it in new applications.
|