0

I am developing a plugin that has a long-running function for setting up a load of posts of a custom post type. I want to run this function asynchronously. In order to do this, I have tried something like this:

add_action( 'admin_post_my_action', 'my_long_running_function' );

$url = admin_url( 'admin-post.php' );
$args = [
    'method'      => 'POST',
    'timeout'     => 50,
    'redirection' => 5,
    'blocking'    => true,
    'headers'     => [] ,
    'body'        => [
        'action' => 'my_action'
    ],
    'cookies'     => []
];
$response = wp_remote_post( $url, $args );

if ( is_wp_error( $response ) ) {
    $error_message = $response->get_error_message();
    printf(
        'Something went wrong: %s',
        $error_message
    );
} else {
    echo 'Response:<pre>';
    print_r( $response );
    echo '</pre>';
}

Please note that I know it has 'blocking' => true, which won't run asynchronously but I changed it to that so I could see the response.

In my_long_running_function, the results are emailed to the site admin. I am also outputting some debugging messages and have a break point in NetBeans.

The function is not getting called via wp_remote_post, the response from which is as follows:

Array
(
    [headers] => Requests_Utility_CaseInsensitiveDictionary Object
        (
            [data:protected] => Array
                (
                    [date] => Wed, 01 Jul 2020 05:23:22 GMT
                    [server] => Apache/2.4.37 (Win64) PHP/7.2.14
                    [x-powered-by] => PHP/7.2.14
                    [expires] => Wed, 11 Jan 1984 05:00:00 GMT
                    [cache-control] => no-cache, must-revalidate, max-age=0
                    [x-frame-options] => SAMEORIGIN
                    [referrer-policy] => strict-origin-when-cross-origin
                    [content-length] => 0
                    [content-type] => text/html; charset=UTF-8
                )
        )
    [body] => 
    [response] => Array
        (
            [code] => 200
            [message] => OK
        )
    [cookies] => Array
        (
        )
    [filename] => 
    [http_response] => WP_HTTP_Requests_Response Object
        (
            [response:protected] => Requests_Response Object
                (
                    [body] => 
                    [raw] => HTTP/1.1 200 OK
Date: Wed, 01 Jul 2020 05:23:22 GMT
Server: Apache/2.4.37 (Win64) PHP/7.2.14
X-Powered-By: PHP/7.2.14
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Content-Length: 0
Connection: close
Content-Type: text/html; charset=UTF-8
                    [headers] => Requests_Response_Headers Object
                        (
                            [data:protected] => Array
                                (
                                    [date] => Array
                                        (
                                            [0] => Wed, 01 Jul 2020 05:23:22 GMT
                                        )
                                    [server] => Array
                                        (
                                            [0] => Apache/2.4.37 (Win64) PHP/7.2.14
                                        )
                                    [x-powered-by] => Array
                                        (
                                            [0] => PHP/7.2.14
                                        )
                                    [expires] => Array
                                        (
                                            [0] => Wed, 11 Jan 1984 05:00:00 GMT
                                        )
                                    [cache-control] => Array
                                        (
                                            [0] => no-cache, must-revalidate, max-age=0
                                        )
                                    [x-frame-options] => Array
                                        (
                                            [0] => SAMEORIGIN
                                        )
                                    [referrer-policy] => Array
                                        (
                                            [0] => strict-origin-when-cross-origin
                                        )
                                    [content-length] => Array
                                        (
                                            [0] => 0
                                        )
                                    [content-type] => Array
                                        (
                                            [0] => text/html; charset=UTF-8
                                        )
                                )
                        )
                    [status_code] => 200
                    [protocol_version] => 1.1
                    [success] => 1
                    [redirects] => 0
                    [url] => http://my-site/wp-admin/admin-post.php
                    [history] => Array
                        (
                        )
                    [cookies] => Requests_Cookie_Jar Object
                        (
                            [cookies:protected] => Array
                                (
                                )
                        )
                )
            [filename:protected] => 
            [data] => 
            [headers] => 
            [status] => 
        )
)

I have tried invoking this via a url to admin-posts.php:

http://my-site/wp-admin/admin-post.php?action=my_action

This works as expected, with email sent and debugging messages output.

Given that the request above works and is a GET request, I have also tried my call to wp_remote_post with 'method' => 'GET', and I have tried with wp_remote_get. Neither worked.

I have also stepped through all the code that send the request and handles the response. Nothing helps to indicate the cause of the problem.

Any help on solving this much appreciated, even advice on how to debug invoking admin-post.php via wp_remote_post. This is my first experience of wp_remote_post. Or even an alternative approach to call my function asynchronously.

3
  • 1
    Sorry, what I actually meant in my previous comment is, admin_post_my_action runs only for logged-in users, so your remote call likely didn't call your function because the request wasn't authenticated. But how about using the REST API instead, by creating your own endpoint?
    – Sally CJ
    Commented Jul 1, 2020 at 7:01
  • 1
    @SallyCJ, thank you. You are absolutely correct! If I add a nopriv hook, it works. But that is not great because I need the user to be authenticated. I will look into authenticating the request and also at the REST API.
    – GeeC
    Commented Jul 1, 2020 at 7:29
  • It's also another option to trigger long running scripts from the command line, using PHP and a call to your plugin directly, instead of starting the call via a http request, if you have ssh access, using e.g. wp-cli eval-file. This can be really handy in some cases and can be integrated with your local cron if you want to e.g. trigger the job to run regularly
    – mozboz
    Commented Jul 1, 2020 at 10:26

1 Answer 1

0

Thanks to the comment by Sally CJ, it turned out that the issue was that the user was not authenticated when invoking admin-post.php via wp_remote_post. The simplest solution was to ensure that the wp_remote_post had all the current cookies, as follows:

$nonce = wp_create_nonce( 'my-action' );
foreach ( $_COOKIE as $name => $value ) {
    $cookies[] = "$name=" . urlencode( is_array( $value ) ? serialize( $value ) : $value );
}
$url = admin_url( 'admin-post.php' );
$args = [
    'method'      => 'POST',
    'timeout'     => 50,
    'redirection' => 5,
    'blocking'    => true,
    'headers'     => [] ,
    'body'        => [
        'action'   => 'gpc_nightly_job',
        'my_nonce' => $nonce
    ],
    'headers'   => [
        'cookie' => implode( '; ', $cookies ),
    ]
];
return wp_remote_post( $url, $args );

EDIT: For increased security, I added a nonce to the request, which is checking in the long-running function via wp_verify_nonce.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.