ARCHIVE
Last update: 21:21, 23/01/21

Archived

Webmentions

Parent: Post ideas

If there's one that that has surprised me about setting up webmentions on the new blog it's that creating an endpoint is actually a lot easier that I initially thought. I think I had scared myself into not believing that I could create my own endpoint under the impression that it was going to be beyond my limited coding knowledge.

Fuelled by yesterday's bout of positivity I thought I'd have another look but taking a different tack. Rather than thinking about it as a whole I decided to take a more granular approach and break it down into sections.

Chris Aldrich had previously advised looking at the old versions of the WordPress webmention plugin as they were far simpler than at present. I also decided to start from first principles and check out the W3C Recommendation to check the actual specification.

I was previously conflating the actual mention with everything that goes with it (the microformats markup etc.) but looking at the spec a webmention is simply "a POST request containing the source and target parameters" - that's all. Consequently, an endpoint initially needs to receive that request, verify those parameters and respond accordingly to the sender. It's much easier to get your head around when you look at it like that.

So, a check on the source URL (and response with an error if it doesn't exist) would be something like:

if ( !isset( $_POST['source'] ) ) {
    http_response_code(400);
    exit ('"source" is missing');
}

The same is done for the target URL.

The spec also says that the receiver must check the URLs are of supported schemes (normally http or https) - so simply check if parse_url($_POST['source'])['scheme'] equals http or https. While this is a 'must' according to the spec an endpoint will still function without it and other checks will likely fail in any event.

The receiver "must perform an HTTP GET request on source ... to confirm that it actually mentions the target" so do this using cURL, returning an error if not.

Next up, the spec says the "source document must have an exact match of the target URL" so I perform a quick lookup in the database to confirm that the target URL resolves to a post ID.

If these checks are all passed then you can send a HTTP 202 response confirming the request has been accepted. And that's it from the actual webmention side of things.

That may look a bit long winded so here's the short version:

  • Are there source and target links?
  • Are they valid?
  • Does the source contain the target link?
  • Does the target link point to a valid item?

What happens after that, as the saying goes, is up to you and how you want to process the webmentions.

For a webmention to be really useful you want to be able to check what type of mention it is, who it's from, and what they say. I'm using mf2-php to parse the contents of the source page:

$jsonmf = new Mf2\Parser($contents, $sourceURL, true);
$mf = $jsonmf->parse();

This is so handy as it translates the source page HTML into a standardised JSON array making it easier to pick out the elements like name and webmention type, for example:

$Name = $mf['items']['0']['properties']['author']['0']['properties']['name'][0];

As my 'posts' (or sections) for any given day all exist on the same page I have to go a level deeper if I mention one of my own posts:

$Name = $mf['items']['0']['children']["$s"]['properties']['author']['0']['properties']['name'][0];

(Where 'children' is the collection of 'sections' and $s selects the correct section number.)

Once the required information is collected I add a new comment to the database (using the ID found earlier as the parent post) and send myself an email notification using PHPmailer in the same way as I do for comments.

At present, I'm only checking for Likes and Replies - anything else will just show as a standard mention but I may expand this over time.

Word count: 680