Testing In-House iOS Apps with a Simple Python Web Server

There’re a couple of ways to distribute iOS apps. Everyone knows about the App Store, but the more obscure modes of internal distribution are less common and more opaque. For instance, if you’re experimenting with Enterprise in-house distribution, you’re likely using some sort of mobile device management software. But what if you are a developer trying to test out builds for in-house distribution?

While my favorite way to distribute apps while testing is with TestFlight, device provisioning becomes a pain past a handful of testers. Another way to test a production distribution artifact is to simply sync a device through iTunes after adding your app. The problem I ran into with this method is that it seems to require that you wipe and sync the device as your own… not something I want to do with company-owned testing devices, nor my client’s devices.

The good news is that you can still test and avoid the cost or setup of an MDM solution by simply serving an app directly from your development environment. To make this easier, I’ve made a tiny Python script to automatically create a web server that can provide your devices with a link to install your app directly, without the syncing required with iTunes.

The critical components of an in-house distribution are the .IPA file that contains your application, a manifest.plist file that describes its location, and a web page that contains a specially-formatted link to that manifest file. The link tells MobileSafari to install the app onto your device instead of trying to download it as a normal file. Of course, you’ll need to ensure the app is signed with your distribution certificate and built using a corresponding Enterprise in-house Distribution provisioning profile.

I’m using RubyMotion for app development, which can be configured to build apps for this type of distribution by adding the following lines to my project Rakefile:

app.manifest_assets << { :kind => 'software-package',
   :url => 'http://192.168.1.10:8000/AwesomeApp.ipa' }
app.manifest_assets << { :kind => 'display-image',
   :url => 'http://192.168.1.10:8000/Icon.png' }

When I build the project with rake archive:distribution, it creates the manifest.plist in the build directory along with my application AwesomeApp.ipa.

Now all I need to do is cd into that build directory, execute my simple web server script, and browse to the installation link for my app. Here’s the command:

python in_house_dist_server.py 8000 192.168.1.82

That’s a port number and my current IP or hostname (which must match the one in the manifest.plist.)

The script, included here, is a gist:

import SimpleHTTPServer, BaseHTTPServer, sys
class InHouseRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map['.plist'] = 'text/xml'
    def do_GET(self):
        if self.path == "/index.html":
            self.wfile.write('

Install App

‘) self.send_response(200) return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) BaseHTTPServer.test(InHouseRequestHandler, BaseHTTPServer.HTTPServer)