javascript - Cannot establish AJAX connection ('400 Bad Request')

admin2025-05-31  5

Im trying to create a very basic AJAX script that shows a random post title, just so I at least know I can get AJAX to work.

But I keep getting a 400 error in the Chrome console.

I've been checking my admin-ajax.php URL is correct and have also tried specifying it absolutely, but still no luck

I've tried both GET and POST and neither seem to work

Im building this locally on MAMP, could that be related to my issues?

Here is my template file:

<?php
/* Template Name: Page AJAX */
get_header();
?>

<div class="container-fluid">
    <div class="row">
        <div class="col-8 offset-2">
            <div id="result"></div>
            <button id="load_data">Load Random Post Title</button>
        </div>
    </div>
</div>

<script type="text/javascript">
    jQuery(document).ready(function($) {
        $('#load_data').click(function() {
            var data = {
                action: 'load_random_post_title',
                security: '<?php echo wp_create_nonce("load_random_post_title_nonce"); ?>' // Add nonce for security
            };

            $.ajax({
                url: '<?php echo admin_url("admin-ajax.php"); ?>', // Ensure correct URL
                type: 'POST',
                data: data,
                success: function(response) {
                    $('#result').html(response); // Display the random post title
                },
                error: function(xhr, status, error) {
                    console.error('AJAX error:', status, error); // Log any error
                }
            });
        });
    });
</script>

<?php get_footer(); ?>

And here is from functions.php

// AJAX
function handle_random_post_title_request()
{
    // Verify nonce for security
    if (
        !isset($_POST['security']) ||
        !wp_verify_nonce($_POST['security'], 'load_random_post_title_nonce')
    ) {
        wp_die('Permission Denied: Nonce verification failed.');
    }

    // Get a random post
    $args = array(
        'posts_per_page' => 1,  // Get one post
        'orderby' => 'rand',    // Order by random
        'post_type' => 'post',  // Post type is 'post'
        'post_status' => 'publish' // Only published posts
    );

    $random_post = get_posts($args);

    if ($random_post) {
        // Output the title of the random post
        echo esc_html($random_post[0]->post_title);
    } else {
        echo 'No posts found.';
    }

    wp_die(); // Always call wp_die() to end AJAX requests properly
}

// Hook the AJAX request (both for logged-in and non-logged-in users)
add_action('wp_ajax_load_random_post_title', 'handle_random_post_title_request');
add_action('wp_ajax_nopriv_load_random_post_title', 'handle_random_post_title_request');

Im trying to create a very basic AJAX script that shows a random post title, just so I at least know I can get AJAX to work.

But I keep getting a 400 error in the Chrome console.

I've been checking my admin-ajax.php URL is correct and have also tried specifying it absolutely, but still no luck

I've tried both GET and POST and neither seem to work

Im building this locally on MAMP, could that be related to my issues?

Here is my template file:

<?php
/* Template Name: Page AJAX */
get_header();
?>

<div class="container-fluid">
    <div class="row">
        <div class="col-8 offset-2">
            <div id="result"></div>
            <button id="load_data">Load Random Post Title</button>
        </div>
    </div>
</div>

<script type="text/javascript">
    jQuery(document).ready(function($) {
        $('#load_data').click(function() {
            var data = {
                action: 'load_random_post_title',
                security: '<?php echo wp_create_nonce("load_random_post_title_nonce"); ?>' // Add nonce for security
            };

            $.ajax({
                url: '<?php echo admin_url("admin-ajax.php"); ?>', // Ensure correct URL
                type: 'POST',
                data: data,
                success: function(response) {
                    $('#result').html(response); // Display the random post title
                },
                error: function(xhr, status, error) {
                    console.error('AJAX error:', status, error); // Log any error
                }
            });
        });
    });
</script>

<?php get_footer(); ?>

And here is from functions.php

// AJAX
function handle_random_post_title_request()
{
    // Verify nonce for security
    if (
        !isset($_POST['security']) ||
        !wp_verify_nonce($_POST['security'], 'load_random_post_title_nonce')
    ) {
        wp_die('Permission Denied: Nonce verification failed.');
    }

    // Get a random post
    $args = array(
        'posts_per_page' => 1,  // Get one post
        'orderby' => 'rand',    // Order by random
        'post_type' => 'post',  // Post type is 'post'
        'post_status' => 'publish' // Only published posts
    );

    $random_post = get_posts($args);

    if ($random_post) {
        // Output the title of the random post
        echo esc_html($random_post[0]->post_title);
    } else {
        echo 'No posts found.';
    }

    wp_die(); // Always call wp_die() to end AJAX requests properly
}

// Hook the AJAX request (both for logged-in and non-logged-in users)
add_action('wp_ajax_load_random_post_title', 'handle_random_post_title_request');
add_action('wp_ajax_nopriv_load_random_post_title', 'handle_random_post_title_request');
Share Improve this question edited Apr 14 at 21:14 user303096 asked Apr 14 at 20:23 user303096user303096 1354 bronze badges 1
  • Is the html content restricted in any way ? if the content is public and for unconnected users, the nonce becomes public and has no more utility. – mmm Commented Apr 15 at 6:04
Add a comment  | 

2 Answers 2

Reset to default 2

You're getting a HTTP 400 because there is no ajax handler for load_random_post_title. This is because the only place that handler exists is when that template page is being displayed, and since that never happens on an AJAX request it will never be found. As a result the legacy ajax handler returns 0 with a HTTP code of 400.

Instead, you should move those AJAX handlers to a place that always runs, not a theme template. E.g. a plugin or functions.php

Alternatively instead of using the old AJAX API, instead consider using the new API by registering a REST API endpoint. This gives you a pretty URL, human readable error messages, and built in validation/authentication/sanitizing options that would need to be built from scratch if using admin-ajax.php

here is a proposal with an API endpoint and javascript code in a external file.

the endpoint definition

add_action("rest_api_init", function (\WP_REST_Server $wp_rest_server) {
    
    register_rest_route(
          "MY_PLUGIN"
        , "random_post"
        , [
            "methods" => WP_REST_Server::READABLE, // "GET"
            "permission_callback" => fn (\WP_REST_Request $request) => TRUE,
            "callback" => function (\WP_REST_Request $req) {
                
                $response = [
                    "code" => "not_found",
                ];
                
                
                // Get a random post
                $args = [
                    'posts_per_page' => 1, // Get one post
                    'orderby' => 'rand', // Order by random
                    'post_type' => 'post', // Post type is 'post'
                    'post_status' => 'publish', // Only published posts
                ];
                
                
                $random_posts = get_posts($args);
                
                if (isset($random_posts[0])) {
                    
                    $post = $random_posts[0];
                    
                    $response["code"] = "found";
                    $response["title"] = $post->post_title;
                    $response["permalink"] = get_permalink($post);
                    
                }
                
                
                return $response;
                
            },
        ]
    );
    
    
    
}, 10, 1);

the HTML generation

wp_enqueue_script(
      "MY_PLUGIN/load_random_post_title"
    , "load_random_post_title.js"
    , ["wp-api"] // to retrieve api root in javascript variable wpApiSettings
    , "1" // script version
);

?>
    <div id="result"></div>
    <button id="load_data">Load Random Post Title</button>
<?php

the javascript file

"use strict";


document.addEventListener("DOMContentLoaded", e => {
    
    document.getElementById("load_data").addEventListener("click", e => {
        
        fetch(`${wpApiSettings["root"]}MY_PLUGIN/random_post`)
            .then(r => r.json())
            .then(json => {
                
                const result = document.getElementById("result");
                
                
                if (    "undefined" === typeof json["code"]
                    ||  "found" !== json["code"]
                ) {
                    
                    result["textContent"] = `No posts found.`;
                    
                } else {
                    
                    const post_link = document.createElement("a");
                    
                    post_link["textContent"] = json["title"];
                    post_link.setAttribute("href", json["permalink"]);
                    
                    result.replaceChildren(post_link);
                    
                }
                
                
            })
            .catch(error => console.error(error))
        ;
        
        
    });
    
});
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748641919a313722.html

最新回复(0)