Skip to main content

HTTP, Sessions, Cookies, and APIs

Superglobals

SuperglobalContains
$_GETQuery string parameters
$_POSTForm body parameters
$_REQUESTCombined request data
$_COOKIECookies
$_SERVERServer and request metadata
$_FILESUploaded files
$_SESSIONSession data when sessions are enabled

In WordPress, avoid $_REQUEST when the source should be explicit.

Reading Request Data

$search = isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : '';

Redirects and Cookies

wp_safe_redirect(home_url('/thank-you/'));
exit;
setcookie('myplugin_seen', '1', [
'expires' => time() + DAY_IN_SECONDS,
'path' => COOKIEPATH,
'domain' => COOKIE_DOMAIN,
'secure' => is_ssl(),
'httponly' => true,
'samesite' => 'Lax',
]);

Sessions

session_start();
$_SESSION['key'] = 'value';

WordPress core does not use PHP sessions by default. Prefer cookies, user meta, transients, or custom tables unless sessions are specifically required.

WordPress HTTP API

$response = wp_remote_get('https://api.example.com/items', [
'timeout' => 5,
]);

if (is_wp_error($response)) {
return [];
}
$response = wp_remote_post('https://api.example.com/items', [
'timeout' => 5,
'headers' => [
'Authorization' => 'Bearer ' . $api_key,
],
'body' => [
'email' => $email,
],
]);
$status = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
$headers = wp_remote_retrieve_headers($response);

REST Routes

register_rest_route('myplugin/v1', '/items', [
'methods' => 'GET',
'callback' => 'myplugin_rest_items',
'permission_callback' => '__return_true',
]);
function myplugin_rest_items(WP_REST_Request $request): WP_REST_Response {
$limit = absint($request->get_param('limit')) ?: 10;

return rest_ensure_response([
'limit' => $limit,
'items' => [],
]);
}

AJAX

add_action('wp_ajax_myplugin_action', 'myplugin_ajax_action');
add_action('wp_ajax_nopriv_myplugin_action', 'myplugin_ajax_action');
function myplugin_ajax_action(): void {
check_ajax_referer('myplugin_ajax', 'nonce');

wp_send_json_success(['message' => __('OK', 'my-plugin')]);
}

Webhooks

Validate signatures before processing.

if (! hash_equals($expected_signature, $actual_signature)) {
return new WP_Error('invalid_signature', __('Invalid signature.', 'my-plugin'), ['status' => 401]);
}

Common Pitfalls

  • Omitting HTTP timeouts.
  • Trusting remote JSON shape.
  • Putting private API keys in JavaScript.
  • Using sessions without understanding cache impact.
  • Redirecting after output starts.
  • Missing nonce checks in AJAX handlers.
  • Public REST routes exposing private data.