Skip to content

Instantly share code, notes, and snippets.

@fjarrett
Last active May 10, 2022 15:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fjarrett/6263006c04bd21198e37d73bf5be4ef1 to your computer and use it in GitHub Desktop.
Save fjarrett/6263006c04bd21198e37d73bf5be4ef1 to your computer and use it in GitHub Desktop.
Run a WP-CLI command via an authorized HTTP POST webhook
<?php
/**
* Run a WP-CLI command via an authorized HTTP POST webhook.
*
* curl -X POST https://mysite.com/webhook-wp-cli.php \
* -H 'Content-Type: application/json' \
* -H 'X-Authorization: Bearer MY_SUPER_SECRET_KEY_HERE' \
* -d '[ ["theme", "install"], ["https://downloads.wordpress.org/theme/go.zip"], ["force"], {"user": 1} ]'
*
* RUNNING: wp theme install 'https://downloads.wordpress.org/theme/go.zip' --force --user='1'
*
* NOTE: This uses an 'X-Authorization' header to pass the bearer token since Apache blocks 'Authorization'
* by default. Set some .htaccess rules if you want to use it: https://stackoverflow.com/a/26791450/571000
*/
header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
if ( empty( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== $_SERVER['REQUEST_METHOD'] || empty( $_SERVER['HTTP_X_AUTHORIZATION'] ) ) {
http_response_code( 404 );
exit;
}
$secret = 'MY_SUPER_SECRET_KEY_HERE';
if ( "Bearer {$secret}" !== $_SERVER['HTTP_X_AUTHORIZATION'] ) {
http_response_code( 401 );
echo "401 UNAUTHORIZED\n";
exit;
}
$body = json_decode( file_get_contents( 'php://input' ), true );
if ( empty( $body[0] ) ) {
http_response_code( 400 );
echo "400 BAD REQUEST\n";
exit;
}
$commands = implode( ' ', array_map( 'escapeshellcmd', (array) $body[0] ) );
$args = implode( ' ', array_map( 'escapeshellarg', ! empty( $body[1] ) ? (array) $body[1] : [] ) );
$flags = ! empty( $body[2] ) ? (array) $body[2] : [];
$options = ! empty( $body[3] ) ? (array) $body[3] : [];
foreach ( $flags as &$flag ) {
$flag = sprintf( '--%s', escapeshellcmd( $flag ) );
}
foreach ( $options as $option => &$value ) {
$value = sprintf( '--%s=%s', escapeshellcmd( $option ), escapeshellarg( $value ) );
}
$input = trim( sprintf( '%s %s %s %s', $commands, $args, implode( ' ', $flags ), implode( ' ', $options ) ) );
echo "RUNNING: wp {$input}\n";
exec( "wp {$input} > /dev/null 2>&1 &" ); // Non-blocking.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment