YahnisElsts / plugin-update-checker

A custom update checker for WordPress plugins. Useful if you don't want to host your project in the official WP repository, but would still like it to support automatic updates. Despite the name, it also works with themes.
MIT License
2.26k stars 410 forks source link

JSON returned by the get_metadata URL is missing the download_url #381

Closed EvanShaw closed 4 years ago

EvanShaw commented 4 years ago

I'm using a custom implementation of wp-update-server in a plugin on my companies online store which uses the same technique for handling licenses as described in this blog post. If a customer does not have a license then the download_url will be omitted from the JSON result for get_metadata.

I've verified that the license handling logic is running as expected. When I paste the get_metadata URL with a valid license provided as a query argument in the browser the JSON displayed shows the download_url. However, when I invoke Check for updates manually from the plugins page, the download_url is missing and the following message is displayed in place of the download link: Automatic update is unavailable for this plugin.

As per the authors recommendation, I installed Debug Bar to narrow down the problem but nothing appears amiss. The get_metadata URL displayed in the debug panel is correct, but when I invoke Request Info the download_url in the returned JSON is blank. If I copy the URL directly and paste it into the browser as I described above, the download_url is present.

My suspicion is that the URL which WordPress actually uses is not correct (ie. the license is not being added). Here is the PHP where I instantiate the update checker:

$updateChecker = \Puc_v4_Factory::buildUpdateChecker(
    add_query_arg(
        [
            'update_action' => 'get_metadata',
            'update_slug' => $this->plugin_slug,
            'license' => $license,
        ],
        $updateEndpoint . '/wp-update-server/'
    ),
    $this->plugin_file,
    $this->plugin_slug,
    1
);
$updateChecker->addQueryArgFilter(function ($queryArgs) use ($license) {
    $queryArgs['license'] = $license;
    return $queryArgs;
});

Any help would be greatly appreciated.

YahnisElsts commented 4 years ago

Here are some ideas:

EvanShaw commented 4 years ago

@YahnisElsts Thanks for the suggestions.

End-to-end testing like this is really difficult to debug so I decided to set up parallel client and server environments in Docker containers so I could use XDebug. It turned out to be an issue with our authentication handling on the server end. We verify the clients domain via HTTP_REFERER but the way WordPress sets this in wp_remote_get differs from how we set it in a different client library which uses vanilla cURL. This was causing our authentication API to reject the request.

In short, the bug was in our own code and not yours :+1: . I'll close this issue. Again, thanks for the help!