ASP in a Nutshell (Chapter 6) : The Request Object
The Request object gives you access to the user's HTTP request header and body. It is arguably the most important built-in ASP object to understand, since it is through this object that you will be able to react to the decisions made by the user. Using the Request object, you can dynamically create web pages and perform more meaningful server-side actions (such as updating a database) based on input from the user.
How HTTP Works
I will cover the Request object in detail in just a moment. First, however, it is important for you to understand the basics of the HTTP protocol. With such an introduction, use of the Request object is translated from the realm of the mysterious to the ordinary. For those of you whose eyes are beginning to glaze over, don't worry. This will be only a brief overview of the HTTP protocol.
You probably already know that HTTP is a "transaction" style protocol. The browser (the client) sends a request to the server. The server obeys the request if it can and sends a response back to the client. The server then completely forgets about the transaction. The browser may or may not forget about it.
To illustrate the interaction between web browser and server, let's examine a fairly simple example that illustrates this exchange. The figure below shows Netscape Navigator displaying a very simple form, HELLO.HTM, that prompts the user for her name. When the user clicks the Submit button, a CGI application is invoked on a WebSite server that sends back the page displayed in Figure 2. (Although Navigator and WebSite are used for this example, the exchange between any browser and any server would be more or less identical. Also, although this example uses a CGI application, the HTTP request/response cycle is almost exactly the same as that for ASP applications. For more about CGI-to-ASP conversion, see Appendix A, Converting CGI/WinCGI Applications into ASP Applications.) Let's see how this interchange between browser and server are handled by the protocol:
Figure 1: HELLO.HTM, a simple HTML form
Figure 2: HELLOCGI.HTM, an HTML page created by a CGI application
1) When the user finishes entering the URL for HELLO.HTM, Navigator sends the following stream to the server: [73:send:(179)]GET /hello.htm HTTP/1.0 Connection: Keep-Alive User-Agent: Mozilla/3.0 (Win95; I) Host: pc229.west.ora.com Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
This is a request header. The browser indicates that it wants the server to get the document /HELLO.HTM. Get is more than a generic description of what the server should do; it indicates the HTTP request type. (For details, see "HTTP Request Types," later in this chapter.) The browser also indicates that it's using version 1.0 of the Hypertext Transfer Protocol.
Note that the first line in this HTTP header is actually an artifact of the TCP/IP packet sniffer used in this demonstration and not part of the actual HTTP request sent. The same is true for all HTTP segments in this chapter.
2) The server receives the headers sent by the browser, as shown in the following output produced by our spy program, and processes the request: [21:recv: completed (179)]GET /hello.htm HTTP/1.0 Connection: Keep-Alive User-Agent: Mozilla/3.0 (Win95; I) Host: pc229.west.ora.com Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
3) The server sends the document HELLO.HTM to the browser: [21:send:(535)]HTTP/1.0 200 OK Date: Monday, 30-Sep-98 23:33:00 GMT Server: WebSite/1.1 Allow-ranges: bytes Accept-ranges: bytes Connection: Keep-Alive Content-type: text/html Last-modified: Monday, 30-Sep-98 23:30:38 GMT Content-length: 297 <HTML> <HEAD><TITLE>Hello, World!</TITLE></HEAD> <BODY> <FORM ACTION="/cgi-win/hello.exe" METHOD="POST"> What is your name? <INPUT TYPE="text" NAME="name" SIZE=60><BR> <INPUT TYPE="submit" VALUE="Submit the form"> <INPUT TYPE="reset" VALUE="Clear all fields"> </FORM> </BODY> </HTML>
Here, WebSite sends a total of 535 bytes to the browser. This consists of a response header, followed by a blank line, followed by the HTML document itself. The header fields indicate, among other things, the number of bytes (the Content-length header) and the format (the Content-type header) of the transmitted data. "200 OK" is a status code indicating that the browser's request was fulfilled. The server also indicates that, like the browser, it's using version 1.0 of HTTP.
4) The browser reads the headers and data sent by the server: [73:recv: posted] [73:recv: completed (260)]HTTP/1.0 200 OK Date: Monday, 30-Sep-98 23:33:00 GMT Server: WebSite/1.1 Allow-ranges: bytes Accept-ranges: bytes Connection: Keep-Alive Content-type: text/html Last-modified: Monday, 30-Sep-98 23:30:38 GMT Content-length: 297 <HTML> <HEAD><TITLE>H [73:recv: posted] [73:recv: completed (275)]ello, World!</TITLE></HEAD> <BODY> <FORM ACTION="/cgi-win/hello.exe" METHOD="POST"> What is your name? <INPUT TYPE="text" NAME="name" SIZE=60><BR> <INPUT TYPE="submit" VALUE="Submit the form"> <INPUT TYPE="reset" VALUE="Clear all fields"> </FORM> </BODY> </HTML>
Although two recv operations are required to retrieve the header records along with the document, the total number of bytes read in these two operations equals the total number of bytes sent by the server
5) The browser displays the form asking for the user's name and, when the user fills it out and clicks the Submit button, sends the following to the server: [70:send:(232)]POST /cgi-win/hello.exe HTTP/1.0 Referer: http://pc229.west.ora.com/hello.htm Connection: Keep-Alive User-Agent: Mozilla/3.0 (Win95; I) Host: pc229.west.ora.com Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* [70:send:(69)]Content-type: application/x-www-form-urlencoded Content-length: 14 [70:send:(2)] [70:send:(16)]name=Jayne+Doe
Because the browser is transmitting form data, the HTTP request type is "POST," as the very first header record indicates. Similarly, the Content-length and Content-type records indicate that the browser is transmitting 14 bytes of x-www-form-urlencoded data in the body of the request. This consists of the information input by the user in the form's single data field, the name text box.
6) The server receives the header records and form data transmitted by the browser in the previous step. (Since it's basically identical to the text sent by the browser, we won't duplicate it here.) The URL (/cgi-win/hello.exe) causes the server to launch the CGI application HELLO.EXE and to transmit the form's data to it. The CGI application may do some back-end processing, then builds an HTML document on the fly and returns it to the server.
7) The server returns the HTML document to the browser along with the necessary header records, as the following output from WSock32 Spy shows: [18:send:(422)]HTTP/1.0 200 OK Date: Monday, 30-Sep-98 23:33:10 GMT Server: WebSite/1.1 Allow-ranges: bytes Accept-ranges: bytes Connection: Keep-Alive Content-type: text/html Content-length: 231 <HTML><HEAD> <TITLE>Welcome to this Web Page!</TITLE></HEAD> <BODY><H1>Welcome to Our Web Server!</H1><p><p> Hello, Jayne Doe! We're glad that you took the time out of your busy day to visit us! <HR></PRE></BODY></HTML>
Notice that the server indicates to the browser that it's sending 231 bytes of an HTML document.
8) The browser receives the data stream send by the server and uses it to render the HTML page.
Hopefully, this gives you a fairly good sense of what's involved in the interchange between browser and server. It's important, though, to take a more in-depth look at some of the points that we've touched on only briefly, as well as to cover some additional features that are not included in this simple example.
HTTP Request Types
The request type is passed by the client to the server to indicate what the server should do with the URL that's also supplied by the browser. Although the HTTP specification details a number of request types, like PUT and DELETE, only two are supported by all servers and in common use: GET and POST. A GET request asks the server to "get" a piece of information, typically a document, and return it to the client. If the request includes any additional information, these are appended as arguments to the URL. A POST request, on the other hand, provides the server with information to be "posted" to the URL; typically, it's used to send the contents of an HTML form to the server, or to provide the server with information that's needed for back-end processing. The information itself is contained in the body of the request.
Most servers cannot handle data received from either the POST or GET methods internally. Normally, POST requests, as well as GET requests that also send data to the server, are handled by accessory programs or DLLs (CGI and ISAPI applications and ISAPI filters). Both POST and GET requests can return any kind of data of any size.
While it may seem when transmitting data to a web server that GET and POST are similar, one rule is hard and fast: A GET request must never change anything. Don't write an ASP script that makes changes to a database, for instance, in response to a GET request. The reason for this is discussed in greater detail in the following section, "Form Submission."
GET Versus POST
In the event that you're confused about the difference between these two methods, GET can be used to retrieve any document, POST cannot. On the other hand, both GET and POST can be used to pass data to the object indicated by the URL. When GET is used for this purpose, the data is included in the URL as the argument string; in order to extract this data with Win-CGI, you have to parse the argument string. When POST is used, the data is passed to the server in the body of the request message. So, in cases in which data is sent to the server, GET and POST differ in the method used to transmit that data.
A user enters input into the fields of a form. When the form is submitted, the data contained in each field of the form is transferred to the server, which then passes it to ASP. This data is sent in the format name=value, where name is the name assigned to the field by the NAME= attribute of the <INPUT> tag, and value is the value entered in that field. For example, if the user enters "Archie" in a field prompting for his first name, the browser may send along the string first_name=Archie.
If the form is written to use METHOD=GET, the form data is appended to the URL as an argument string. If the form contains many fields or if fields contain long strings of text, the complete URL can become very large and unwieldy. In addition, the limit of the number of characters submitted in a GET--typically about 2000--is much lower than in a POST.
If the form instead uses METHOD=POST, the name=value pairs are sent as the body of the request instead of being appended to the URL. In addition to the greater ease of handling of POST requests, most servers offer better performance when extracting data from the body of a request than from a URL in the request header.
Always use the POST method with forms that change something or cause any irreversible action (most do). POST is safer and more efficient; GET should never be used to change anything. In developing your ASP scripts, you can decide whether you want to support data passed to your program using the GET method.
HTTP Request and Response
Headers are the most misunderstood part of HTTP, yet understanding their role can make understanding the properties and methods of both the ASP Request and Response objects much easier.
Take a look at any Internet email message. It consists of two parts, the header and the body. The header consists of several lines that describe the body of the message and perhaps the way the message was handled as it was routed to you. The header and body are separated by a blank line. (For more information on header syntax, consult RFC-822.)
An HTTP message (either a request or a response) is structured the same way. The first line is special, but the rest of the lines up to the first blank line are headers just like in a mail message. The header describes the request and its content, if any, or the response and its content.
In an earlier section, "HTTP: A Simple Example," we saw a number of requests from the browser. Here is another example of a simple HTTP request:
POST /cgi-win/hello.exe HTTP/1.0 Accept: image/gif, image/jpeg, */* User-Agent: Mozilla/2.0N (Windows; I; 32Bit) Content-type: application/x-www-form-urlencoded Content-length: 14 [mandatory blank line] name=Jayne+Doe
The first line, which is known as the request-line, describes the type of request (or method )--in this case POST, the URL, and, finally, the version of the HTTP protocol that the client uses. The second line describes the types of documents that the client can accept. The third line is an "extra" header that's not required by HTTP. It gives the name and version of the client software. Following this, as discussed in the section "HTTP: A Simple Example," are two lines describing the information contained in the body of the request.
Everything up to the mandatory blank line is part of the HTTP request header. In addition to the example lines here, there can be other lines in this section. For example, if the browser is sending information contained in a "cookie," that information also will be in the request header.
Below the mandatory blank line is the HTTP request body. In most cases, this section of the request is empty (for example, when the browser is requesting only a static page and is not sending any information). However, when the POST method is used, the information sent to the web server is located in this section of the request.
Here is an example of a simple HTTP response:
HTTP/1.0 200 OK Date: Thursday, 02-Nov-95 08:44:52 GMT Server: WebSite/1.1 Last-Modified: Wednesday, 01-Nov-95 02:04:33 GMT Content-Type: text/html Content-length: 8151 [mandatory blank line] <HTML><HEAD> <TITLE>...
The first line of the response is also special and is known as the status-line. It contains the protocol version the server uses, plus a status code and a reason phrase. The server uses the status code and reason phrase to inform the browser whether it was able to respond to the browser's request; in this case, it's successfully filled the browser's request for a document. The second line contains the date and time the server handled the request. Third is a header line describing the server software and version. The fourth line indicates the date and time when the requested document was last modified. The last two lines describe the type of data and the number of bytes in the requested document. This is followed by exactly one blank line, then the body of the message, which contains the document data that the server is sending back for the browser to display.
As with the HTTP request, everything above the mandatory blank line is considered part of the HTTP response header. Everything below this line is part of the response body.
This chapter covers the ASP Request object, which you can use to access both the header and the body of the HTTP request. The next chapter discusses the ASP Response object, which you use in manipulating the HTTP response from the web server.
The HTTP Request and the ASP Request Object
As mentioned earlier, the ASP Request object allows you to access both the header and body of the HTTP request sent to the web server by the client's browser. The method of retrieving information from the HTTP request is basically the same for an ASP script as it is for a CGI application. The exceptions come not from the actual request mechanics but from how each type of application is loaded into the web server (CGI versus an ISAPI filter), as described in the first two chapters of this book.
Just as with CGI applications, the client browser can send information to an ASP script in two different manners. First, it also can send information by means of an HTML form using the GET method:
<HTML> <HEAD><TITLE>Welcome to the Corp.</TITLE></HEAD> <BODY> <FORM ACTION=" http://mycorp.com/secure.asp" METHOD="GET"> First name: <INPUT TYPE="text" NAME="first_name" SIZE=60><BR> Last name: <INPUT TYPE="text" NAME="last_name" SIZE=60><BR> <INPUT TYPE="submit" VALUE="Submit the form"> <INPUT TYPE="reset" VALUE="Clear all fields"> </FORM> </BODY> </HTML>
When the client submits a GET request, the information about the request is appended to the end of the request URL as name/value pairs separated by ampersands and preceded by a question mark. Each name corresponds to an element in the form. For example, suppose the user entered Horatia and Thompson into the two fields in the last example and clicked on the Submit button. The submission of the preceding form is, as far as the server is concerned, identical to the following:
This is an important point. Following this example, consider the following line of code:
If the user were to type this into the address line or click on a link containing the preceding as a URL, the web server would treat that resulting HTTP request exactly as if the information had been sent as part of a form using the GET request. From within your ASP application, you can access this information through the QueryString collection of the Request object. For example:
<% strFirstName = Request.QueryString("first_name") %>
will initialize the strFirstName variable to the value sent in the first_name parameter. The QueryString collection is discussed in detail later in this chapter.
Just as with CGI applications, you also can send information to an ASP script using the POST method. In this case, instead of being part of the HTTP request header, the information would be in the body of the request object:
<HTML> <HEAD><TITLE>Welcome to the Corp.</TITLE></HEAD> <BODY> <FORM ACTION="http://mycorp.com/secure.asp" METHOD="POST"> First name: <INPUT TYPE="text" NAME="first_name" SIZE=60><BR> Last name: <INPUT TYPE="text" NAME="last_name" SIZE=60><BR> <INPUT TYPE="submit" VALUE="Submit the form"> <INPUT TYPE="reset" VALUE="Clear all fields"> </FORM> </BODY> </HTML>
This form's submission would result in an HTTP request similar to the following:
POST /secure.asp HTTP/1.0 Accept: image/gif, image/jpeg, */* User-Agent: Mozilla/2.0N (Windows; I; 32Bit) Content-type: application/x-www-form-urlencoded Content-length: 35 [mandatory blank line] first_name=horatio&last_name=aubrey
For your application to manipulate the information sent in that HTTP request, you would have to use the Form collection of the Request object:
<% strFirstName = Request.Form("first_name") %>
This will initialize the strFirstName variable to the value sent in the first_name parameter. The Form collection is discussed in detail later in this chapter.
The ASP Request Object
The properties, collections, methods, and events of the ASP Request object are as follows:
In the previous discussion of ASP and the GET and POST methods, we saw that information from a GET is retrieved by using the QueryString collection and that information from a POST is retrieved by using the Form collection. This is true, but there is a simpler way: you do not have to specify a collection. For example, the code:
strName = Request("name")
returns the value of the "name" key regardless of the collection in which it's located, because IIS searches all collections. When you specify a value in this manner, ASP looks through each Request object collection in the following order:
The variable you are initializing will receive the value in the first instance of the name/value pair whose name matches the string requested. For this reason, it is important to realize that if you have the same name/value pair in two or more collections, you will receive the first one found according to the preceding sequence, unless you specify a particular collection.
As with the other collections in the ASP object model, all the collections discussed in this chapter for the Request object support the Item and Key properties, the Count method, and the For..Each construct.
Var = Request.TotalBytes
The TotalBytes property is a read-only value that specifies the total number of bytes posted to the web server by the client in the HTTP request body. This property is important when preparing to read data from the request body using the BinaryRead method of the Request object.
Receives the total number of bytes in the client's HTTP request body when it posts data to the web server. Remember that the TotalBytes property is read-only.
In this example, assume that the user has responded to the following form:
<HTML> <HEAD><TITLE>File Upload Form</TITLE></HEAD> <BODY> <FORM ENCTYPE = "multipart/form-data" ACTION= "http://mycorp.com/secure.asp" METHOD="POST"> Select a file to upload: <INPUT TYPE="file" NAME="filename"><BR> <INPUT TYPE="submit" VALUE="Submit the form"> </FORM> </BODY> </HTML>
You can use the TotalBytes property to determine exactly how many bytes of information were sent to the web server in the HTTP request:
<% ' The following code retrieves the total number of ' bytes sent in the user's HTTP request. This variable ' is then used to determine how many bytes to retrieve ' using the Request object's BinaryRead method. Dim lngTotalByteCount Dim vntRequestData lngTotalByteCount = Request.TotalBytes vntRequestData = Request.BinaryRead(lngTotalByteCount) %>
Most often, you will not need to access data in the HTTP request body at the low level provided by the Request object's BinaryRead method and so will not need to retrieve the value of the TotalBytes property. You will use the Form and QueryString collections for almost all of your request data access.
In the preceding example, the value of vntRequestData represents the total bytes sent, not just the byte count of the uploaded file; i.e., all header-related HTTP request information also counts toward this total. To retrieve from the preceding upload only the file contents, you would have to parse out the header information.
The ClientCertificate collection of the Request object provides access to the certification fields of the client's digital certificate. Client certificates are sent to the web server when a client's browser supports the Secure Sockets Layer and that browser is connected to a web server also running the Secure Sockets Layer (i.e., the URL starts with https:// rather than http://). For example, if you were using Internet Explorer 4.01 and were connected to an Internet Information Server web site with SSL running, each request made by your browser would include your client certificate, if you have one. The fields of a client certificate are specified in the International Telecommunications Union (ITU) recommendation X.509.
The ClientCertificate collection, like the other ASP collections, has the following properties:
strKeyName = Request.ClientCertificate.Key(3) strKeyValue = Request.ClientCertificate.Item(strKeyName)
strKeyValue = Request.ClientCertificate.Item("ISSUER")
As with other ASP collections, you can retrieve the value of any field of the Cookies collection through the use of the Item property. Note that, because Item is the default property of the collection, the syntax can be abbreviated so that it does not explicitly show the use of the Item property. For example:
strClientCountry = Request.ClientCertificate("Issuer")
is only an abbreviated form of:
strCertIssuer = Request.ClientCertificate.Item("Issuer")
The available Key values are predefined and are as follows:
1. send in the following output listing is a sockets function that sends a stream in a connected socket. In the output, 73 identifies the socket, while 179 is the value returned by the function and represents the total number of bytes sent.
2. The recv function is used to receive data from a socket. In the output, the initial number, 21, represents the socket used by the server. "Completed (179)" indicates the function's return value, in this case that it completed normally by receiving 179 bytes. Note that this corresponds to the number of bytes sent by the browser.
Contribute to IDR:
To contribute an article to IDR, a click here.