How the heck can I make local revs to the App and proxy them through the FB back-end while still keeping the App running live for my millions of satisfied customers</sarcasm>?
When I was launching Forgiveness, my first attempt at a Facebook App via RoR, I ran into one of the typical developer quandries. How do I debug this thingy I’m building?
I sought advice from Steve Enzer, and his answer was ‘create a separate FB App id’. Yep, you can do that. I’m sure it works just fine. However, I wanted to come up with a single-App solution, you know, just because.
My App backbone was based upon Facebooker, a great gem for just such purposes. And assuming that you’re using that gem, you’re provided with:
% rake facebooker:tunnel:start
Which starts up the traditional server tunnel to your local dev box; Facebook’s proxy won’t know the difference. I’ve also set up my canvas page URLs and the like with a fixed IP – according to FB’s best practices, because they don’t want to deal with all the DNS resolution stuff – and it listens on port 80 with a dedicated context. So, I’ve got my facebooker.yml set up for port 3100:
Here I omit the upstream cluster configs, and I’ll let the comments speak for themselves … I always try to keep track of red herrings at least at some level, and there were several I bumped into while trying out this solution. The best approach that I found was to simply set a cookie with a naming convention that nginx could parse (yes, there is a regex performance penalty here). The development context is routed locally, which is where the tunnel is waiting to pick up and run with it.
Setting the cookie, well that’s another trick. Though not much of one. Of course your App is completely masked behind the apps.facebook.com domain, so trying to set a cookie to your internal domain (eg. IP) through your browser isn’t so easy, and it’s repetetive manual work. So, just bake it into a dedicated action in your App:
Then use /:controller/tunnel/1 to engage, and /:controller/tunnel/0 to disengage. A little bit of auth logic, and you’re good to go.
NOTE: If your screen reader is reading this, please contact me at admin@cantremember.com ... because it shouldn't.
FIXME: build this dynamically based upon the maximum content in any sub-Element of this Element.
I will call this my "Safari Reader Counterweight".
In some of my Posts, I have huge code excerpts, etc.
Safari Reader, at least in iOS, will identify the 'main Element', the one it features, based upon its content length.
Sometimes those code excerpts get identified as the 'main Element', and the Post is borked in Safari Reader mode.
This is a counter-weight; it gives the <main> Element additional content so that it gets featured, algorithmically.
Yes, it increases the payload of every page (@see FIXME above).
But not by that much.
Then again, this is a guess as to how much content any given Element could contain.
If it's not enough, BOOM, Safari Reader looks like crap.
So, here's a great article on how to enable Safari Reader on your site.
It's mostly guesswork, but those guesses helped me debug this obtuse goddamn problem.
Oh, and look, you can enter and exit Reader programmatically.
JavaScript can fix anything.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.
I promise I will never cut-and-paste lines of text simply to add Element payload.