Receiving 3rd party webhooks on a locally hosted web app

I spent today integrating Paddle into Readership. Readership isn’t hosted anywhere publicly available yet, so I needed a way to feed Paddle’s webhooks to a URL on localhost.

Enter UltraHook. Having used it for a few hours, I really can’t fault it. It’s lightweight, it’s stable and it just works.

Getting up and running is a 3 step process if you already have Ruby installed:

1​. Install it:

$ gem install ultrahook

2​. Configure it (you get an API key when you sign up):

$ echo "api_key: YOUR_API_KEY" > ~/.ultrahook

3​. Run it:

$ ultrahook paddle-alerts 8888/api/v1/paddle/alerts/new

The command in step 3 tells UltraHook to listen for webhooks POSTed to http://paddle-alerts.USERNAME.ultrahook.com and forward them to localhost:8888/api/v1/paddle/alerts/new on your machine. All that’s left to do is to tell the service you’re receiving webhooks from to send them to the generated ultrahook.com URL.

Proof of concept cyberattacks

Andy Greenberg has written an excellent piece for Wired which looks at Russia’s quickly-becoming-annual proof of concept cyberattacks on the Ukrainian power grid:

Noting the precise time and the date, almost exactly a year since the December 2015 grid attack, Yasinsky felt sure that this was no normal blackout.

[…]

Yasinsky knows by now that even as he’s analyzing last year’s power grid attack, the seeds are already being sown for 2017’s December surprises.

Failing to plan is planning to fail. They planned:

Once the circuit breakers were open and the power for tens of thousands of Ukrainians had gone dead, the hackers launched another phase of the attack. They’d overwritten the firmware of the substations’ serial-to-­ethernet converters—tiny boxes in the stations’ server closets that translated internet protocols to communicate with older equipment. By rewriting the obscure code of those chunks of hardware—a trick that likely took weeks to devise—the hackers had permanently bricked the devices, shutting out the legitimate operators from further digital control of the breakers.

Concepts are proven for a reason. I suppose only time will tell if the reason this time ’round is to deter other nations or to engage them:

A grid attack on American utilities would almost certainly result in immediate, serious retaliation by the US. Some cybersecurity analysts argue that Russia’s goal is simply to hem in America’s own cyberwar strategy: By turning the lights out in Kiev—and by showing that it’s capable of penetrating the American grid—Moscow sends a message warning the US not to try a Stuxnet-style attack on Russia or its allies, like Syrian dictator Bashar al-Assad. In that view, it’s all a game of deterrence.

[…]

But for those who have been paying attention to Sandworm for almost three years, raising an alarm about the potential for an attack on the US grid is no longer crying wolf.

Handling optional trailing commas in `macro_rules!`

Here’s a nice little trick I discovered whilst dissecting the router! macro for iron-middlefiddle. You can optionally allow trailing commas in a macro with the following:

$(,)*

If you’re unfamiliar with the macro syntax in Rust then here’s how it breaks down:

// Start a repetition:
$(
// It's a repetition of commas:
,
// End the repetition:
)
// Allow zero or more of these repetitions:
*

And here’s how it looks in action:

macro_rules! router {
    (
        // Start a repetition:
        $(
            // The pattern of each repetition:
            $route_id:ident: $method:ident $glob:expr => $handler:expr
        // End the repetition:
        )
        // Each repetition will be separated by a comma:
        ,
        // Allow one or more of these repetitions:
        + 
        // Allow zero or more commas after the last repetition:        
        $(,)*
    ) => { ... };
}

As you have probably deduced, it’s not an ideal solution because it not only makes zero or one trailing commas valid; but also two, three, four or sixteen trailing commas valid. Overall though, I think this is a nicer way of handling things than the two other options:

  1. Explicitly stating you expect or do not expect a trailing comma, resulting in a compile error if the user respectively does not or does leave a trailing comma. This option gets a bonus thumbs-down because such a treatment of trailing commas is not in keeping with the rest of the Rust language.

  2. Adding repetitious code in the macro to explicitly handle zero or one (and only one) trailing commas.

Introducing iron-middlefiddle: Route specific middleware made easy in Iron

Route specific middleware is a fairly common need in web apps. As soon as you introduce something like authentication into the mix, you’ll probably want a way to apply middleware to routes you only want users to be able to access if they’re logged in.

As things stand, route specific middleware in Iron is a repetitive and messy business, which is where iron_middlefiddle comes in. It provides a macro which turns the tricky into the trivial, allowing you to add middleware to any number of routes within a Router easily.

let mut frontend_router = Router::new();

// Add some `frontend_router` routes and the middleware they should use:

middlefiddle! {
    router => frontend_router,
    routes => {
        lorem: get "/lorem" => controllers::lorem::index,
        ipsum: get "/ipsum" => controllers::ipsum::index,
        dolor: get "/dolor" => controllers::dolor::index,
    },
    middleware => {
        Middleware::BeforeMiddleware => middleware::auth::TokenValidity,
    },
};

// Add some more `frontend_router` routes that aren't going to need the middleware:

frontend_router.get("/amet", controllers::amet::index, "amet");

iron_middlefiddle is well documented and available on crates.io. Naturally, you’ll find its source code in the repo on GitHub.

DeltaE 0.2.0

In the wee hours of this morning I released DeltaE 0.2.0, my Rust implementation of the CIEDE2000 colour differentiation algorithm. The update brings 2 main improvements:

  1. A new from_rgb method which will handle the conversions to LAB values for you and return the colour difference.

  2. An extensive test suite based on the data in Table 1 of “The CIEDE2000 Color-Difference Formula: implementation Notes, Supplementary Test Data, and Mathematical Observations”

With the addition of those tests, the library has reached a point where I feel comfortable in the thought of others using it. If no issues arise in the next month or so, I’ll bump this release to 1.0.0.

You’ll find DeltaE 0.2.0 in the usual places: crates.io & GitHub.

Setting Iron’s response MIME type with middleware

If your JSON API is powered by Iron, you may well have a lot of duplicate code that sets the MIME type of each Response. Something like this:

use iron::mime::Mime;

pub fn example_handler(req: &mut Request) -> IronResult<Response> {
    let mime = "application/json".parse::<Mime>().unwrap();

    // …

    Ok(Response::with((mime, status::Ok, some_json)))
}

As we can see above, the code for setting a MIME type is generic and doesn’t need anything except a Response to modify. It is therefore a prime AfterMiddleware candidate, which once implemented will remove the need for the code repetition in each and every one of our routes’ handlers. Here’s a very brief AfterMiddleware description from the docs:

AfterMiddleware receive both a Request and a Response and are responsible for doing any response post-processing.

Read on, there’s more »

Now in beta: DeltaE – a library for quantifying the difference between two colors

I have just published the first beta of my first public crate. DeltaE is a pure-Rust implementation of the International Commission on Illumination’s CIEDE2000 algorithm.

The goal of the algorithm is to put a number on the difference our eyes perceive when looking at two colours. If you’re interested in the details, then I recommend this rundown. In short though:

  • If the returned value is less than 1, then the human eye can’t distinguish between the two colours.
  • If the returned value is greater than 1, then we humans can see a difference when presented with the two colours.
  • The greater the return value, the more difference the human eye perceives.

This crate was written to be used in a project I’m currently tinkering with. It’ll come out of beta once I, and hopefully others, have used it some more and I have improved the test suite.

It is entirely based on Zachary Schuessler’s Javascript implementation of the algorithm. He is also the author of the aforementioned rundown so a huge thank you goes out to him for his work.

Jimmy Cuadra’s “The highs and lows of Rust”

Back in February 2016, Jimmy Cuadra wrote a post about “The highs and lows of Rust”. He too came to Rust from dynamic web-focused languages and he too “clicked” with it:

Rust has a reputation of having a much higher learning curve [than Go], which of course affects its popularity. I really haven’t been able to understand why, but somehow Rust just clicks with my mental model of programming […]

I’ve been wondering what helped make Rust click for me. The best answer I have come up with is that its basic function structure is relatively familiar to anyone who’s worked with Javascript. function becomes fn, and the parameter and return types are typed but other than that it’s more or less the same. I think that that familiarity with such a core and highly used part of the language helps a lot.

Read on, there’s more »

How to seed a Postgres database with Knex

Diesel is my ORM & query builder of choice for Rust projects, it doesn’t provide a way to seed a database though. I went looking for a seeding crate and came up empty handed, so settled on looking for a Node package instead. Though even NPM had a surprisingly limited number options, I found Knex which has served me well so far.

Though we’ll just be using Knex’s seeding functionality in this post, it too is a fully functional query builder. Though I haven’t used it for query building, it’s syntax looks pretty nice and I would certainly consider it for any future Node projects.

Let’s get cracking then. I’m going to assume that you already have Postgres setup on your machine.

Read on, there’s more »

Notes from building a WordPress theme in 2017

It’s been a good many years since I last put a WordPress theme together. I spent some time last weekend doing just that however, owing to the poor performance of WordPress’ default “Twenty Seventeen” theme which I had been using since switching back.

Over the course of the past 14 years, WordPress has grown to become the content management system of choice for a huge percentage of websites. With such a large reach, each decision has the potential to impact vast quantities of people, which is why I find the amount of stuff WP shoves into a webpage by default disturbing.

Read on, there’s more »

A third of the Web now runs on Nginx

w3techs:

Nginx, the fastest growing web server, has reached 33.3% market share. Seven years ago, it only had 3.9%. On average, every minute one of the top 10 million websites starts to use Nginx.

The telling statistic yielded by the research is that nearly 77% of all sites (including this one) supporting HTTP/2 run on Nginx. With Apache’s HTTP/2 module still classed “experimental”, and only around 13% of the Web using HTTP/2, Nginx seems destined to continue eating away at Apache’s popularity.

How to set up environment varying code in your Rust web app

There are times when you’ll want your app to run different code depending on which environment it’s in: development, production, etc.

For example: You provide your templating engine with a baseurl variable. In production, you want it to point to https://my-app.com, but in development you want it to point to http://localhost:8888.

We can accomplish this in Rust-y web apps with environment variables and the dotenv crate, as demonstrated in the following post.

Read on, there’s more »

Back to WordPress

Last August I outlined some new rules for myself when it comes to blogging and they have worked well. The only thing outlined which I haven’t adhered to is “no categories” — there’s just too much differently themed content on this site to make it sane to navigate without them.

The “no categories” rule fell into the “get out of your own way” bucket. I’ve reached a point where I need add a sister rule, the “get out of my way” rule, the contents of which would read something like: “If you think about writing a post then remember some pain-point in the process which makes you reluctant to do so, get rid of the pain-point”. For me, that pain-point has become Jekyll.

Read on, there’s more »

MVC mappings for CtrlP

It’s been a while since I last shared anything Vim related.

My favourite somewhat-recent addition to my .vimrc is a set of CtrlP mappings for searching directly within an apps model, view, controller, or helper directories.

nnoremap <leader>c :CtrlP src/controllers<cr>
nnoremap <leader>h :CtrlP src/helpers<cr>
nnoremap <leader>m :CtrlP src/models<cr>
nnoremap <leader>v :CtrlP src/views<cr>

Chances are, your MVC directories don’t live in src/ in your project. If you build Rails apps for example, then you’ll want to change that to app/.

I first saw these mappings in Gary Bernhardt‘s dotfiles, so full credit to him.

Saving users a click with `autofocus`

Much of today was spent working on signing forms — sign in, sign up, password reset — and consequently browsing around other web apps to see how they approach them.

Done properly, these are single purpose pages designed to get users in and out of them as quickly as possible. To that end, it’s interesting that a vast majority of them don’t autofocus the first input in the form, leaving the user to reach for the mouse and click it themselves.

Read on, there’s more »

Deleting the contents of a directory in Rust

There are various ways to delete the contents of a directory. You could, for example, delete the directory itself with fs::remove_dir_all and then create a new directory with the same name.

A more refined solution, which will go through the contents of a directory and delete each child without actually destroying and recreating the parent, looks like this:

use std::fs::{self, ReadDir};
use std::io::Error;

fn main() {
    let demo_dir = fs::read_dir("/path/to/dir");
    delete_dir_contents(demo_dir);
}

fn delete_dir_contents(read_dir_res: Result<ReadDir, Error>) {
    if let Ok(dir) = read_dir_res {
        for entry in dir {
            if let Ok(entry) = entry {
                let path = entry.path();

                if path.is_dir() {
                    fs::remove_dir_all(path).expect("Failed to remove a dir");
                } else {
                    fs::remove_file(path).expect("Failed to remove a file");
                }
            };
        }
    };
}

ReadDir provides an iterator over the contents of a directory. It’s worth noting that it’s a non-recursive iterator, which is why we’re using fs::remove_dir_all here. That standard function will delete a directory along with all of it’s contents, which avoids us having to recursively walk and delete. As I’m here, I’ll recommend the walkdir crate for all of your recursive walking needs though.

Note: In production, the delete_dir_contents function is the sort of thing you’d probably want to break out into a utils module.

Matching, saving and replacing text with the regex crate

Work continued on flyingV, one of my side-projects, last week. An interesting challenge I came up against was to find all of the matches to a particular regex across multiple files. For each match, I needed to save a specific portion of it then replace a specific portion of it with a new string.

The following uses the regex crate and is written in Rust. Captures are a feature of the regex language, not the regex crate itself though so if you aren’t familiar with them, there should still be something in this post for you.

To business then. The pattern I was matching against was any tera for loop containing quotes. Here’s an example loop I’d want to match:

{% for page in "20*/**/*" %}

Read on, there’s more »