cocoahttpserver
Pending Contractが続く日々ですが、PCから iPhoneアプリデータのバックアプ&リストアやデータ編集できるようにしてみました。
今のところ、PCから iPhoneアプリデータに簡単にアクセスする方法はないようで、ちょっと面倒だけどアプリ自身が Webサーバになってブラウザから編集するという方法を試しています。
cocoahttpserver
cocoahttpserverは iPhoneアプリに組み込み可能な 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 に限定して、サンプルコードの流用でごまかしました。誰か簡単にカスタマイズできるように実装してくれないかなぁ。