Sunday, June 26, 2016

Running gsap (greensock) examples in SystemJS

Once again, nobody spells these things out in detail, leading to a little frustration during late night hacking. I figured it out for you:

$ jspm install jquery jquery-ui css npm:gsap
And in your app.js:

import $ from 'jquery';
import gsap from 'gsap';
import 'jquery-ui';
import 'jquery-ui/themes/base/jquery-ui.css!css';
Theeeere we go! Now the only thing left to do is to prefix gsap modules, e.g. gsap.TweenMax instead of TweenMax.

Thursday, June 2, 2016

Creating a serial GCD queue with custom QoS priority

Did you know the system dispatch queues are defined as concurrent? That was an annoying bug on my side to fix. So, today's adventure: create our own, serial worker queue with a custom priority. Priority is defined in two stages: the QoS class (from highest to lowest: interactive, user initiated, utility, or background), and a scheduling priority relative to said class.

We have to specify the queue's behavior using a struct built by dispatch_queue_attr_make_with_qos_class, and what Apple's official docs as of today tell you about relative_priority won't even compile. Also, it's wrong, so I won't repeat it here.

Fortunately, there is a place with the correct information - usr/include/dispatch/queue.h:

 @param relative_priority
A relative priority within the QOS class. This value is a negative offset from the maximum supported scheduler priority for the given class.
Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY results in NULL being returned.

So, to create a serial queue with maximum priority in the default class:

self.queue = dispatch_queue_create(
 "OHAI",
 dispatch_queue_attr_make_with_qos_class(
  DISPATCH_QUEUE_SERIAL,
  QOS_CLASS_DEFAULT,
  0
 )
);


whereas minimum priority would be:


self.queue = dispatch_queue_create(
 "OHAI",
 dispatch_queue_attr_make_with_qos_class(
  DISPATCH_QUEUE_SERIAL,
  QOS_CLASS_DEFAULT,
  QOS_MIN_RELATIVE_PRIORITY
 )
);


Wednesday, June 1, 2016

SSL-enabled Django runserver development

It used to be the case that you could safely ignore SSL encryption in your web application up to the point where the thing goes live. I mean, who cares about man-in-the-middle attacks in your home network, right?

Not anymore.

Not only is it good practice to encrypt everything by default, but nowadays iOS apps enable app transport security out of the box. In short this means every unencrypted http connection just silently dies.

While it is possible to have a debug app build that includes exceptions to this rule, I think it's better to be as consistent between debug and release as possible. So let's get going - it's not actually complicated. You will need:
  • A (preferrably free) dynamic DNS provider or a proper DNS hostname pointing to your public IP address.
  • A valid SSL certificate for your public hostname. Letsencrypt is free and works well.
  • A web server acting as reverse proxy to Django. This is the main difference to a typical Django development setup. I'm using nginx.
  • Port forwarding from the public IP to your web server, if required.
Not too frightening.

First, make sure your web server is actually reachable under its public hostname. As a quick sanity check, configure it for SSL and let it serve some static files:


server {
    listen 443 ssl;

    server_name localhost your-public-hostname.example.com;

    ssl_certificate /etc/letsencrypt/live/your-public-hostname.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-public-hostname.example.com/privkey.pem;
    ... ssl hardening parameters omitted for brevity ...

    location / {
        root   /srv/helloworld;
        index  index.html index.htm;
    }
}

open https://your-public-hostname.example.com/ in your browser and check for SSL errors. I like to completely disable http by forwarding all requests to https:

server {
    listen 80;
    server_name localhost your-public-hostname.example.com;
    return 301 https://$host$request_uri;
}

sweet.

Now configure it to reverse proxy to Django. The cool part: you don't actually need a WSGI daemon for that - while Django's own runserver is not suitable for production, it's totally fine here. 

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://localhost:8000/;
    proxy_buffering off;
}

(Add some source IP firewalling if desired though - a Django app in DEBUG mode should not be exposed to the public.)

And that's it! Not even a staticfiles setup is required (unless you choose so). Enjoy your SSL-enabled Django development!