Http Server in Objective-C
Here’s the translation of the HTTP server example from Go to Objective-C:
Our first HTTP server example demonstrates how to create a basic server using the Foundation framework.
#import <Foundation/Foundation.h>
@interface MyHTTPServer : NSObject <NSNetServiceDelegate>
@property (nonatomic, strong) NSNetService *netService;
@property (nonatomic, strong) NSFileHandle *listeningSocket;
@end
@implementation MyHTTPServer
- (void)startServer {
// Create a socket
CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL);
if (!socket) {
NSLog(@"Error creating socket");
return;
}
// Set socket options
int yes = 1;
setsockopt(CFSocketGetNative(socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
// Set up the IPv4 endpoint
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(addr4));
addr4.sin_len = sizeof(addr4);
addr4.sin_family = AF_INET;
addr4.sin_port = htons(8090);
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
// Bind the socket
CFDataRef addressData = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr4, sizeof(addr4));
if (CFSocketSetAddress(socket, addressData) != kCFSocketSuccess) {
NSLog(@"Error binding to address");
CFRelease(addressData);
CFRelease(socket);
return;
}
CFRelease(addressData);
// Set up the listening file handle
CFRunLoopSourceRef socketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), socketSource, kCFRunLoopDefaultMode);
CFRelease(socketSource);
self.listeningSocket = [[NSFileHandle alloc] initWithFileDescriptor:CFSocketGetNative(socket) closeOnDealloc:YES];
// Start listening for connections
[self.listeningSocket acceptConnectionInBackgroundAndNotify];
// Set up notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNewConnection:) name:NSFileHandleConnectionAcceptedNotification object:nil];
NSLog(@"Server started on port 8090");
}
- (void)handleNewConnection:(NSNotification *)notification {
NSDictionary *userInfo = notification.userInfo;
NSFileHandle *fileHandle = userInfo[NSFileHandleNotificationFileHandleItem];
// Handle the incoming request
NSData *data = [fileHandle readDataToEndOfFile];
NSString *request = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// Process the request and generate a response
NSString *response;
if ([request containsString:@"GET /hello"]) {
response = @"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhello\n";
} else if ([request containsString:@"GET /headers"]) {
response = [self generateHeadersResponse:request];
} else {
response = @"HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found\n";
}
// Send the response
[fileHandle writeData:[response dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
// Continue listening for new connections
[self.listeningSocket acceptConnectionInBackgroundAndNotify];
}
- (NSString *)generateHeadersResponse:(NSString *)request {
NSMutableString *responseBody = [NSMutableString string];
NSArray *lines = [request componentsSeparatedByString:@"\r\n"];
for (NSString *line in lines) {
if ([line containsString:@": "]) {
[responseBody appendFormat:@"%@\n", line];
}
}
NSString *response = [NSString stringWithFormat:@"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n%@", responseBody];
return response;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MyHTTPServer *server = [[MyHTTPServer alloc] init];
[server startServer];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
This Objective-C implementation creates a basic HTTP server that listens on port 8090. It includes two routes: /hello
and /headers
.
The startServer
method sets up a socket and starts listening for incoming connections. When a new connection is accepted, the handleNewConnection:
method is called to process the request and send a response.
The /hello
route simply responds with “hello”, while the /headers
route echoes back the headers from the incoming request.
To run the server:
- Save the code in a file named
HTTPServer.m
. - Compile the code:
$ clang -framework Foundation HTTPServer.m -o HTTPServer
- Run the compiled binary:
$ ./HTTPServer
The server will start and listen on port 8090. You can then use curl
or a web browser to access the routes:
$ curl localhost:8090/hello
hello
$ curl localhost:8090/headers
This example demonstrates basic HTTP server functionality in Objective-C, although it’s worth noting that for more complex server applications, you might want to consider using higher-level frameworks or libraries designed specifically for web servers in iOS/macOS development.