kuhboeejoe
kuhboeejoe

Reputation: 350

Run a simple Objective-C executable as Apache CGI

I am trying to run simple Objective-C CGI programs on my Mac. I am using Apache2 and am running OS X Mountain Lion (if that matters). Take for example the following code:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {

       // insert code here...
       NSLog(@"Content-type: text/plain\r\n");
       NSLog(@"From Cupertino, CA, we say, 'hello, World!'\r\n");

    }
return 0;
}

I compiled the above code, and copied the executable to the CGI directory, renamed it with a .cgi extension, and gave it run permissions.

I used pretty basic settings on Apache, and on my httpd.conf, I ensured the usage of Option s ExecCGI as as directive, and I uncommented AddHandler cgi-script .cgi so that it would run CGI scripts. It worked when I ran a python CGI script, but returned an error when running my executable:

90 [Sun Feb 09 20:01:33 2014] [error] [client ::1] 2014-02-09 20:01:33.247 testCGI.cgi[1498:707] Content-type: text/plain\r
2991 [Sun Feb 09 20:01:33 2014] [error] [client ::1] 2014-02-09 20:01:33.248 testCGI.cgi[1498:707] From Cupertino, CA, we say, 'hello, World!'\r
2992 [Sun Feb 09 20:01:33 2014] [error] [client ::1] Premature end of script headers: testCGI.cgi

Any ideas why I am getting Premature end of script headers: testCGI.cgi?

Upvotes: 0

Views: 600

Answers (2)

malhal
malhal

Reputation: 30699

There is a simple fastcgi Objective-C framework to create web services and websites called Backtoweb.

It builds to a bundle so can contain frameworks, and amazingly you can even debug with Xcode.

It's a block-based API and in this example, visiting http://mywebsite/hello/world calls this block which outputs a single text line.

@implementation HelloWorldHandler
+(void)initializeHandlers:(FCHandlerManager*)handlerManager
{
    [handlerManager
        addHandler:^BOOL(FCURLRequest *request, FCResponseStream *responseStream, NSMutableDictionary* context)
        {
            [responseStream writeString:@"Hello world !"];

            return NO; //do not try to find another handler
        }
     forLiteralPath:@"/hello/world" pathType:FCPathTypeURLPath priority:FCHandlerPriorityNormal];
}
@end

Upvotes: 0

Emmanuel
Emmanuel

Reputation: 2917

This is because NSLog write to stderr not stdout. You will do better to use the class method +fileHandleWithStandardOutput of NSFileHandle to do this. Like :

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
         NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput];
         // don't use \r\n, but \n\n else you got an error "malformed header from script. Bad header=" 
         NSData *data = [@"Content-type: text/html\n\n" dataUsingEncoding:NSASCIIStringEncoding];
        [stdout writeData: data];

         data = [@"From Cupertino, CA, we say, 'hello, World!'\n\n" dataUsingEncoding:NSASCIIStringEncoding];    
        [stdout writeData: data];
     }
     return 0;
}

Upvotes: 1

Related Questions