Send As POST
Until recently, my site had sections called “Reading” and “Photos” that were links to Pocket and Instagram, respectively. I’ve been working reduce how much I interact with the dopamine-lever of the social web, and also to control anything that I publish to this wonderful place called the internet.
To make that easier, I developed an application (or more accurately, a few of them) that lets me publish photos and bookmarks to this site from my iPhone/Mac. Here’s how it works.
The site itself is running on Jekyll, so I did some shell scripting/housekeeping to move files around and thus create categories for all existing posts. I updated the nginx config so that old links would still work. The goal was to create a structure where I could just write a markdown file to a directory (namely either /photos or /reading) and regenerate the site in order to add a photo post or bookmark.
To make it as flexible as possible, I wanted to be able to send the information needed to create the photo post or bookmark via an HTTP POST request. I used Sinatra to create a very simple app to receive the request and write the markdown file to the right directory. There’s one endpoint for creating a photo and one endpoint to create a bookmark. The endpoint for a photo also saves the incoming image to a file and puts the filename in the markdown file. The authorization system is also very simple and based on the shared secret pattern - incoming requests need to include a
secret parameter that matches the one specified in the app config.
With the server listening for POST requests, now we just need a way to easily fire them off. The most common situation is that I’ll be on my phone and want to publish a photo that I like. On iOS this happens via the Share button, which presents a number of options and services for how to share an image. As of iOS 8, third party developers can create Share Extensions, meaning their app can appear in that list. So I wrote an app called Send As POST that, when installed, appears on the list. When you choose to share a photo via Send As POST, you can specify a caption for the photo, which will be sent along with the image data to the URL you choose. The trickiest part of this photo part was getting the background task to run and not get terminated after the share card disappears, which doesn’t allow enough time to upload a normal photo.
With photos working, I generalized the code to also allow sharing of web pages. Here, I wanted to make it easy to create Daring Fireball style bookmarks, with a pull quote, title, and a comment. For a while I went down the rabbit hole of thinking that I should do this by enabling the Share Extension to share text (as opposed to a web page), but it turned out that isn’t really possible. If you highlight text on a web page, though, and then use the Safari share button, the highlighted text gets sent as the
quote parameter along with your comment and title of the page (or whatever you change it to).
For completeness, I wanted to also be able to share photos and web pages from my laptop. Luckily macOS has the same concept of a Share Extension so it was relatively straightforward to take the iOS app and adapt it to macOS with some changes to the UI. The biggest hangup was/is the fact that it doesn’t look like the image EXIF data is making it through the conversion. In the iOS app it comes through in the image which means I can parse it on the server side and date the post to match the date that the photo was taken. I added this as an issue - the macOS version is also open source, and also in the Mac App Store.
There’s a lot of duplication in the code between the two apps, so the next step (in addition to closing the open issues I’ve been adding along the way) would probably be to DRY up the code base, either by creating a shared framework or just by adding a macOS target to the iOS project (I didn’t actually realize you could do this until just now. Whoops.) It would also be nice to find some way to promote the apps and fund future development but I’m thinking their audience is much too niche. We’ll see.