Skip to Content Skip to Search Go to Top Navigation Go to Side Menu
Search on Site

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.

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:

  1. // create the object
  2. SimpleHTTPResponder  *simpleHTTPResponder = [[SimpleHTTPResponder alloc] init];
  3.  
  4. // listen on port 80
  5. [simpleHTTPResponder listen:80];
  6.  
  7. // where to serve files from - in this case, a folder
  8. // called "httpdocs" under "resources" in the
  9. // application bundle
  10. [simpleHTTPResponder setWebRoot:[[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingString:@"/httpdocs"]];
  11.  
  12. // set the index file
  13. [simpleHTTPResponder setIndexFile:@"index.html"];
  14.  
  15. // open port and wait for requests
  16. [simpleHTTPResponder startListening];

Bonjour publishing

To broadcast the availability of your server on the local network, use the following method:

  1. // set the service name for Bonjour
  2. [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:

  1. // set the object that will respond to requests
  2. [simpleHTTPResponder setDelegate:myResponder];

The object passed to setDelegate should implement the category SimpleHTTPWillRespond (found in SimpleHTTPResponder.h). This prototcol defines two methods:

  1. - (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request;
  2. - (SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request;

In the simplest case just call the default methods on the server object we created above:

  1. - (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
  2. {
  3.     return [simpleHTTPResponder processRequest:request];
  4. }
  5.  
  6. - (SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request
  7. {
  8.     return [simpleHTTPResponder processRequest:request];
  9. }

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:

  1. // returns the requested URL
  2. - (NSURL *)url;
  3.  
  4. // POST or GET
  5. - (NSString *)method;
  6.  
  7. // The headers that accompany the request
  8. - (NSDictionary *)headers;
  9.  
  10. // Get an individual header
  11. - (NSString *)getHeader:(NSString *)byName;
  12.  
  13. // The body of the request
  14. // e.g. in the case of POST, the raw POST query string
  15. - (NSData *)body;
  16.  
  17. // The current connection
  18. - (SimpleHTTPConnection *)connection;
  19.  
  20. // The time of the request
  21. - (NSDate *)date;
  22.  
  23. // Get a POST variable by name
  24. - (NSString *)postVar:(NSString *)byName;
  25.  
  26. // Get a GET variable by name
  27. - (NSString *)getVar:(NSString *)byName;

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:

  1. // Adds a header to the repsonse
  2. - (void)addHeader:(NSString *)key withValue:(NSString *)value;
  3.  
  4. // Defaults to "text/html"
  5. - (void)setContentType:(NSString *)mimeType;
  6.  
  7. // Defaults to 200
  8. - (void)setResponseCode:(int)code;
  9.  
  10. // Sets the response body (e.g. read in binary file data or similar)
  11. - (void)setContent:(NSData *)toData;
  12.  
  13. // A convenience method for sending back text (e.g. HTML)
  14. - (void)setContentString:(NSString *)toString;

So you could do something like the following:

  1. - (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
  2. {
  3.     if([request getHeader:@"magicHeader"] != NULL) {
  4.         SimpleHTTPResponse *response = [[SimpleHTTPResponse alloc] init];
  5.         [response setContentString:@"You sent a magic header"];
  6.        
  7.         return response;
  8.     }
  9.    
  10.     return [simpleHTTPResponder processRequest:request];
  11. }

Please send me any comments/suggestions.

Changelog

Version 0.2

Initial release

Version 0.1

Internal testing version

Popularity: 1% [?]