Difference between revisions of "A Short Guide to AJAX programming"
SteveBaker (Talk | contribs) (→HTTP) |
SteveBaker (Talk | contribs) (→HTTP) |
||
Line 24: | Line 24: | ||
<?php header("Content-type: text/css"); ?> | <?php header("Content-type: text/css"); ?> | ||
− | ...which tells PHP to emit a header with the MIME type "text/css" rather than the usual "text/html" so that the browser knows that this ".php" file is really a style sheet. | + | ...which tells PHP to emit a header with the MIME type "text/css" rather than the usual "text/html" so that the browser knows that this ".php" file is really a style sheet. A regular ".css" file has the same MIME header - but Apache generates it automatically because of the filename extension. To pick another example, our Mozilla app-store manifests start with: |
+ | |||
+ | <?php header("Content-Type: application/x-web-app-manifest+json"); ?> | ||
+ | |||
+ | ...which generates the MIME header that the App Store expects. | ||
== Parameters: GET and POST == | == Parameters: GET and POST == |
Revision as of 07:39, 10 March 2011
First let's review how HTTP works to get web pages into the browser:
HTTP
When the web browser wants a page from a website, the following sequence ensues:
- The browser sends an HTTP (HyperText Transport Protocol) command over the Internet to the server containing the URL of the web page - and then sits around waiting for a response.
- On the server, a program called "httpd" (the HTTP daemon) is "awoken" by the operating system and handed the URL. Most websites run "Apache" as their HTTP daemon - but there are others form Microsoft and elsewhere that work kinda similarly. I'm going to talk about Apache because that's what we use.
- What Apache does next depends on the filename extension:
- If there is no filename (eg "http://tubagames.net") then it changes the filename internally to "index.html" (or if that doesn't exist: "index.php").
- Most of the time (eg with an ".html" or ".css" or ".gif"/".png"/".jpg" file), Apache finds the file, sticks a special "MIME header" on to the top of it - and sends it back to browser.
- If the URL that's requested has the ".php" extension, then Apache grabs the file - hands it to the PHP interpreter, which runs the program, which generates some output (including a "MIME header") that gets handed back to Apache...which passes it on to the browser. The PHP code essentially "prints out" the web page and exits...but more complicated things are also possible (such as checking for cookies and running other Linux programs on the server).
- If the URL is a ".cgi" file and is stored in a certain special "cgi-bin" directory then Apache runs it as a regular Linux program (probably written in C++ - but could be something else). Whatever the CGI program writes to the output (with 'printf' or 'cout <<...'). Apache takes whatever it outputs and sends it to the client. Because we don't want any random idiot with a browser to be able to run any program whatever on our server, CGI program executable have to be kept in a certain approved directory (which in our case is called "cgi-bin"). Apache knows where this directory is - and refuses to run programs from anyplace else.
- When the browser gets the resulting data - be it a file, results from PHP or results from CGI - it looks for the "MIME header" - and either displays it, or sets the style or whatever - depending on what the header tells it to do.
The "MIME header" is pretty important because that's how the browser knows what to do with the file.
When Apache serves up a simple file (eg an HTML file or an image), it sticks a MIME header on it that tells the browser what type it is based on the file extension. When you run PHP programs, the header is added automatically by PHP - but in CGI programs, you have to be sure to write the header out yourself.
For an HTML file, the header is just:
Content-Type:text/html
...and the browser knows what to do with text/html files...it displays them. The "text/html" part is called the "MIME type"...which actually comes from email protocols...but that's another story. Aside from the standard MIME types like "text/html" and "image/jpeg", you can tell your browser to do things like running special plugins for particular MIME types. That's how the Flash plugin gets invoked when Apache sends the browser a ".swf" file. There are special header types for CSS files and other stuff like that. You'll notice that (for example) all of our ".php"-ized CSS files start with something like:
<?php header("Content-type: text/css"); ?>
...which tells PHP to emit a header with the MIME type "text/css" rather than the usual "text/html" so that the browser knows that this ".php" file is really a style sheet. A regular ".css" file has the same MIME header - but Apache generates it automatically because of the filename extension. To pick another example, our Mozilla app-store manifests start with:
<?php header("Content-Type: application/x-web-app-manifest+json"); ?>
...which generates the MIME header that the App Store expects.
Parameters: GET and POST
GET
When you go to (say) Google and type in something into an HTML form, the resulting HTTP request contains an extended URL which has some extra "stuff" on the end (these are called "GET parameters":
http://www.google.com/index.html#q=helloworld
...everything after the "#" is a set of parameters separated by the "&" character. The example above sets the "q" (query? question?) parameter to the value "helloworld" - which Google obediently searches for. If you really do a Google search for "helloworld", it'll produce this kind of mess:
http://www.google.com/#sclient=psy&hl=en&q=helloworld&aq=f&aqi=&aql=&oq=&pbx=1&bav=on.2,or.&fp=bfd1057040a6822d
Which sets a BUNCH of parameters:
sclient=psy hl=en <== Searching in English q=helloworld <== We understand this one! aq=f aqi= aql= oq= pbx=1 bav=on.2,or. fp=bfd1057040a6822d
...who knows what all of those mean?!)
This data really only means something for PHP and CGI URL's. PHP and C++ "CGI" programs can read those parameters and do something different depending on what they are...Google clearly uses the value in the "q" parameter to determine what to search for.
This approach to sending data is called the "GET" method (I don't know why) and it's considered kinda old-fashioned.
In C++, the "GET" parameters are passed to the program on the command line - so you have to parse argc and argv to read them.
In PHP, there is an array called "$_GET[]" that's indexed by the parameter name and contains whatever parameters are passed this way. So if you were writing your own Google clone using PHP, you could say:
if ( isset ( $_GET ['q'] ) ) { $result = searchTheWebFor ( $_GET['q'] ) ; echo "Found these results:
" ; echo $result ; } else echo "Error: No search terms entered?" ;
POST
The "POST" method is more suited to PHP and CGI - but you have to send it from JavaScript code. In this method, the URL is just the name of the program you want to talk to. The data can be any ASCII text and it's sent to C++ on the standard input (so you can read it with "cin" or "scanf" or whatever). In PHP, it works the same way as "GET" except that the array is called "$_POST[]".
So here is a complete C++ CGI program:
#include <stdio.h> #include <stdlib.h> int main ( int argc, char **argv ) { char buffer [ 1024 ] = { 0 } ; fread ( buffer, 1024, 1, stdin ) ; printf ( "Content-Type:text/html\n\n" ) ; // IMPORTANT: DON'T CHANGE THIS LINE! printf ( "<HTML><HEAD></HEAD>\n" ) ; printf ( "<BODY>"\n" ) ;printf ( "
You typed:
" ) ;printf ( " %s\n", buffer ) ; printf ( "</BODY>\n" ) ; }
...if you call this (let's say) "echo.cpp", compile it on the server, place it into the "cgi-bin" directory with a ".cgi" file: "cgi-bin/echo.cgi"...then you can go to your browser and type in it's URL (complete with the ".cgi" extension) and you'll get back a web page that is a blank page with "You typed:" as an 'H1' heading. There won't be anything beneath that because we didn't send it any "POST" data.
For that, we need to make a web page with this form in it:
<form action="cgi-bin/echo.cgi" method="post"> Type something: <input type="text" name="something" /> <input type="submit" /> </form>
(Notice: 'method="post"', that invokes this method to sending data to the program, and 'action="cgi-bin/echo.cgi"' - which is the URL of the C++ program we wrote.)
Now you can type something into that text box - and whatever you type will go up to the server, the echo.cgi program will be run, it reads our input and prints out an HTML document with that text inside.
AJAX
So...finally...we're ready to talk about the "AJAX" thing. This uses the "POST" method to send data from the browser to the server and back again...exactly like we did above. But the difference here is that JavaScript code sends the command to the server - and JavaScript reads the result instead of the web browser itself.
Because JavaScript programs have to run quickly and then end - they can't hang around waiting for the round trip to the server. So you set up an "event" for the browser to call when the results come back.
First, create a global variable to hold the transaction information:
var http_request = new XMLHttpRequest () ;
...the original idea was to use this technique to fetch XML documents - but you can actually get any kind of data this way.
Then, you need to define a function that'll be called when the results arrive. Let's call it "updateFunc"...and we'll talk about what it does in just a moment.
When you want to talk to the server:
function sendToServer ( myData ) { http_request.onreadystatechange = updataFunc ; http_request.open ( "POST", "http:whatever.com/cgi-bin/echo.cgi", true ); http_request.setRequestHeader( "Content-type","application/x-www-form-urlencoded"); http_request.send ( myData ) ; }
...notice the name of our results gathering function "updateData" being set as the "onreadystatechange" event. Note that the full URL is passed on the second line, some "Content-type" header for the message (don't change this!) - and finally, we pass in the data - which actually causes the message to be sent.
The "updateFunc" function is called when the results are returned:
function updateFunc () { var ready = http_request . readyState ; if ( ready != 4 ) return ; var stat = http_request . status ; if ( stat != 200 ) return ;
var result = http_request . responseText ;
// ...do something with the result...
alert ( result ) ; // Pop up an alert box with the results in it. }
The system may call your "net_update" function several times - indicating various stages of progress before you actually have the message available. Hence the first two lines of the function check various status stuff and just return if there is a problem or if the message didn't actually arrive yet. When we finally get our answer, the "result" variable will be a string containing whatever the CGI or PHP program sent you.