SimpleHTTPd
Introduction
This is a simple web server written in Objective C/C using the Cocoa/Core Foundation and packaged up as a Framework for inclusion in your own projects.
It's based on SimpleHTTPServer written by Jurgen of Cultured Code (ace Mac developer of Things fame) and the article he wrote for O'Reilly's Mac Dev Center. The improvements I've made include handling POST requests, handling requests split over multiple packets, changing the listening port, the web root, and advertising the server via Bonjour.
Download
Source is included in the download. This application requires Mac OS 10.5 Leopard or above as it uses features of Objective C 2.0 including the garbage collector.
- SimpleHTTPd 68KB
Installation
Open the DMG and use XCode to import the framework into your project.
Ensure that it is copied into your application bundle as part of the build phase.
Usage
See the following for an example:
-
// create the object
-
SimpleHTTPResponder *simpleHTTPResponder = [[SimpleHTTPResponder alloc] init];
-
-
// listen on port 80
-
[simpleHTTPResponder listen:80];
-
-
// where to serve files from - in this case, a folder
-
// called "httpdocs" under "resources" in the
-
// application bundle
-
[simpleHTTPResponder setWebRoot:[[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingString:@"/httpdocs"]];
-
-
// set the index file
-
[simpleHTTPResponder setIndexFile:@"index.html"];
-
-
// open port and wait for requests
-
[simpleHTTPResponder startListening];
Bonjour publishing
To broadcast the availability of your server on the local network, use the following method:
-
// set the service name for Bonjour
-
[simpleHTTPResponder publish:@"MyWebsite"];
Pass in any string you like and it should show up in Bonjour aware application such as Safari's "Bonjour Bookmarks" list.
Server delegate
The default behaviour of SimpleHTTPd on receipt of a request is to look in the specified web root folder for the requested file - if it finds it, the file will be piped to the user, otherwise a 404 will be sent. To implement more advanced functionality, we need to set a delegate object to process incoming requests. This is done via the following method:
-
// set the object that will respond to requests
-
[simpleHTTPResponder setDelegate:myResponder];
The object passed to setDelegate should implement the category SimpleHTTPWillRespond (found in SimpleHTTPResponder.h). This prototcol defines two methods:
-
- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request;
-
- (SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request;
In the simplest case just call the default methods on the server object we created above:
-
- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
-
{
-
return [simpleHTTPResponder processRequest:request];
-
}
-
-
- (SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request
-
{
-
return [simpleHTTPResponder processRequest:request];
-
}
Otherwise you'll want to examine the SimpleHTTPRequest object.
Responding to a request
If you wish to override the default behaviour, first, have a look at the public methods exposed by the SimpleHTTPRequest object:
-
// returns the requested URL
-
-
// POST or GET
-
-
// The headers that accompany the request
-
-
// Get an individual header
-
-
// The body of the request
-
// e.g. in the case of POST, the raw POST query string
-
-
// The current connection
-
- (SimpleHTTPConnection *)connection;
-
-
// The time of the request
-
-
// Get a POST variable by name
-
-
// Get a GET variable by name
The request handler methods need to return a SimpleHTTPResponse object. HTTP responses are made up of headers and optionally a response body. The relevant setter methods exposed by a SimpleHTTPResponse object are:
-
// Adds a header to the repsonse
-
-
// Defaults to "text/html"
-
-
// Defaults to 200
-
- (void)setResponseCode:(int)code;
-
-
// Sets the response body (e.g. read in binary file data or similar)
-
-
// A convenience method for sending back text (e.g. HTML)
So you could do something like the following:
-
- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
-
{
-
if([request getHeader:@"magicHeader"] != NULL) {
-
SimpleHTTPResponse *response = [[SimpleHTTPResponse alloc] init];
-
[response setContentString:@"You sent a magic header"];
-
-
return response;
-
}
-
-
return [simpleHTTPResponder processRequest:request];
-
}
Please send me any comments/suggestions.
Changelog
Version 0.2
Initial release
Version 0.1
Internal testing version
Popularity: 2% [?]