cocoahttpserver

Pending Contractが続く日々ですが、PCから iPhoneアプリデータのバックアプ&リストアやデータ編集できるようにしてみました。
今のところ、PCから iPhoneアプリデータに簡単にアクセスする方法はないようで、ちょっと面倒だけどアプリ自身が Webサーバになってブラウザから編集するという方法を試しています。

cocoahttpserver

cocoahttpserveriPhoneアプリに組み込み可能な Webサーバです。サーバを起動すると Bonjourでサービス通知もしてくれるようです。

サンプルアプリ

こちらにあるサンプルアプリをビルドして実行するとサーバが起動し、画面にサーバのURLを表示します。ブラウザからアクセスすると、ドキュメントフォルダにあるファイルの一覧が表示されます。さらにファイルリンクからファイルをダウンロードしたり、フォームからファイルをアップロードできます。

カスタマイズ

カスタマイズには HttpConnectionクラスのサブクラスでhttpResponseForURIメソッドをオーバーライドします。このサブクラスはサンプルでは MyHttpConnectionになります。

- (NSObject<HTTPResponse> *)httpResponseForURI:(NSString *)path
{
	NSLog(@"httpResponseForURI: %@", path);
	NSString *method = [(NSString *)CFHTTPMessageCopyRequestMethod(request) autorelease];

	NSObject<HTTPResponse> *result = nil;
	
	if ([path isEqualToString:@"/"]) {
		result = [self resourceIndex:method];
	} else if ([path isEqualToString:@"/hoge"]) {
		result = [self resourceHoge:method];
	} 
	
	return result;
}

HttpConnectionオブジェクトの path属性は HTTPリクエストのパスです。この例では pathの値を見て、メソッドをディスパッチしています。

- (NSObject<HTTPResponse> *)resourceHoge:(NSString*)method {
	
	if([method isEqual:@"POST"]) {
		// POSTデータを読み込む		
	} else {
		NSString* outcontent = @"<html><body><p>hoge</p></body></html>";
		NSData *browseData = [outcontent dataUsingEncoding:NSUTF8StringEncoding];			
		return [[[HTTPDataResponse alloc] initWithData:browseData] autorelease];			
	}	
}

この例では HTTP methodタイプで処理を分岐させています。POSTでない場合は GETを想定しています。処理の流れは、HTMLデータを文字列として作成、UTF8にエンコーディング、HTTPDataResoponseオブジェクトを生成となります。
HTTPDataResoponseオブジェクトは HTTPメッセージのボディ部分のみを扱うため、レスポンスヘッダのカスタマイズはできないようです。このため、303リダイレクトなどを返すには HttpConnectionクラスを修正する必要があります。

POSTの場合はフォームからの urlencodedデータなどを処理することになるのですが、ここは省略しました。というのも POSTで送られてくるチャンクデータの読み取り処理からコーディングしないといけないので、結構なコーディング量になります。。サンプルには multipartフォーム形式でファイルがアップロードされる場合のコードがあるので、それを参考にして実装することになります。
#僕は面倒なんで、POSTデータの形式を multipart/form-data に限定して、サンプルコードの流用でごまかしました。誰か簡単にカスタマイズできるように実装してくれないかなぁ。