This section describes how the sample application
SamplePost
posts information to an HTTP URL and download the URL's response using the URL Access Manager function
URLDownload
.
Listing 2-2 shows the header file for the application,
SamplePost.h
, which contains definitions of the URL from which data is to be downloaded (
kSampleURL
) and the structure
urlDownInfo
, as well as declarations of the function
DoSamplePost
, which calls
URLDownload
, and a system event callback function,
MyURLCallbackProc
, which is a place holder for code that handles system events that occur during the download.
SamplePost.h
#define kSampleURL "http://www.internic.net/cgi-bin/itts/whois" typedef struct urlDownInfo *URLDownInfoPtr; typedef struct urlDownInfo { URLReference urlRef; FSSpec * destination; Handle destinationHandle; URLOpenFlags openFlags; URLSystemEventProcPtr eventProc; void * userContext; Boolean done; OSStatus errorCode; } URLDownloadInfo; static void DoSamplePost (); pascal OSStatus MyURLCallbackProc( void*, EventRecord * );
SamplePost is a multi-threaded application. As a result, in Listing 2-3, SamplePost's main function calls the Memory Manager functions
MaxApplZone
and
MoreMasters
in its main function. Note that all URL Access Manager functions are threaded with Thread Manager cooperative threads. These threads are nonreentrant on PowerPC.
SamplePost's main function
#include <stdio.h> #include <Events.h> #include <Threads.h> #include <Processes.h> #include <Files.h> #include "URLAccess.h" #include "SamplePost.h" int main (void){ OSStatus err = noErr; // Call MaxAppleZone() when using the Thread Manager. MaxApplZone(); for (i = 0; i < 20; i++) { MoreMasters(); }
Listing 2-4 shows
SamplePost
calling the function
URLAccessAvailable
to verify that the URL Access Manager is available. If the URL Access Manager is available,
DoSamplePost
is called.
Listing 2-4 Verifying the availability of the URL Access Manager
// Make sure the URL Access Manager is available. if ( URLAccessAvailable()) { DoSamplePost(); } else { // Call error handling function. }
In Listing 2-5,
DoSamplePost
defines a
URLDownloadInfo
structure named
myRef
that is uses to store information for calling
URLDownload
. The
DoSamplePost
function then calls
NewHandle
to allocate the memory in which the downloaded information will be stored, creates a URL reference, and stores it in
myRef.urlRef
.
Allocating memory and creating a URL reference
static void DoSamplePost ( void){ OSStatus err = noErr; ThreadID threadID = 0; URLDownloadInfo myRef; Handle downloadHandle = NULL; long downloadSize = 0; printf( "<·>DoSamplePost() Enter\n"); downloadHandle = NewHandle(0); if ( downloadHandle == NULL) { // Call error handling function. } // Create a URLReference err = URLNewReference( kSampleURL, &myRef.urlRef ); if ( err != noErr) { // Call error handling function. }
As shown in Listing 2-6,
DoSamplePost
calls the function
URLSetProperty
to set the HTTP request method property value to the 4-byte string
"POST"
and the value of the HTTP request body property value to the 19-byte string
"whois_nic=apple.com"
. When you set the property identified by
kURLHTTPRequestBody
, the URL Access Manager automatically adds the length of the value identifed by
kURLHTTPRequestHeader
to the request, so you do not need to set the request header explicitly.
Setting URL properties
URLSetProperty (myRef.urlRef, kURLHTTPRequestMethod, "POST", 4); URLSetProperty (myRef.urlRef, kURLHTTPRequestBody, "whois_nic=apple.com", 19);
Next,
DoSamplePost
uses the remaining fields of the
myRef
structure to store values that will be used as parameters for calling
URLDownload
.
DoSamplePost
sets
myRef.destination
to
NULL
. When
NULL
is provided as the destination parameter to the
URLDownload
, the calling application indicates that the downloaded data is not going to be written to a file on disk.
DoSamplePost
sets
myRef.destinationHandle
to the value of
downloadHandle
, which is the location in memory at which the downloaded data is to be stored.
DoSamplePost
sets
myRef.OpenFlags
to
kURLDisplayProgressFlag
. When the value of the
openFlags
parameter to
URLDownload
is
kURLDisplayProgressFlag
,
URLDownload
displays a progress indicator during the download process. You may wish to provide a system event callback function to handle system events that occur.
DoSamplePost
sets
myRef.eventProc
to the address of the SamplePost application's system event callback function. When
DoSamplePost
calls URLDownload, it will specify
myRef.eventProc
as the
eventProc
parameter. If a system event occurs while the progress indicator is displayed, the URL Access Manager will call the function specified by the
eventProc
parameter and will pass to it the value of the
userContext
parameter, which is described next.
DoSamplePost
sets
myRef.userContext
to point to
myref
. When
DoSamplePost
calls
URLDownload
, it will specify
myRef.userContext
as the
userContext
parameter. Your application can use the user context to set up its context when the system event callback function is called.Listing 2-7 illustrates setting these values.
Setting the URLDownload parameters
myRef.destination = NULL; myRef.destinationHandle = downloadHandle; myRef.openFlags = kURLDisplayProgressFlag; myRef.eventProc = &MyURLCallbackProc; myRef.userContext = &myRef; myRef.errorCode = 0;
Once the URL reference has been created, its properties set, and the parameters for
URLDownload
prepared,
DoSamplePost
is ready to call
URLDownload
, as shown in Listing 2-8. If the download is successful,
DoSamplePost
calls the function
URLGetProperty
to obtain the size of the downloaded data using the
downloadSize
parameter.
Listing 2-8 Calling the URLDownload function
err = URLDownload( myRef.urlRef,myRef.destination,myRef.destinationHandle, myRef.openFlags, myRef.eventProc, myRef.userContext); myRef.errorCode = err; if ( myRef.errorCode != noErr) { // Call error handling function. } else { // Successful download. Get the size of the downloaded data. err = URLGetProperty(myRef.urlRef, kURLResourceSize, &downloadSize, 4); if ( err != noErr) { // Call error handling function. }
In Listing 2-9
DoSamplePost
calls
SetHandleSize
to set the size of
downloadHandle
to
downloadSize + 1
and sets the value of the last byte of downloaded data to
NULL
. DoSamplePost calls
printf
to display the data, and concludes by disposing of the URL reference.
Listing 2-9 Displaying the downloaded data
downloadSize = GetHandleSize(downloadHandle); SetHandleSize(downloadHandle, (downloadSize+1)); (*myRef.destinationHandle)[downloadSize] = NULL; printf( "<·>==================== Downloaded Data ==================\n" ); printf( "%s", *myRef.destinationHandle ); DisposeHandle(downloadHandle); URLDisposeReference(myref.urlRef);
Listing 2-10 shows a placeholder for SamplePost's system event callback function. The
userContext
parameter can be used to associate any particular call of
URLDownload
with any particular call of the system event callback function.
Listing 2-10 SamplePost's system event callback function
pascal OSStatus MyURLCallbackProc ( void *userContext, EventRecord *event ) { printf( "<·>System callback thread fired! Thread: %u\n", userContext ); return 0; }