Making WordPress.org

Changeset 15016


Ignore:
Timestamp:
07/28/2026 09:04:15 PM (12 hours ago)
Author:
obenland
Message:

Events API: Return a proper JSON response when a request fails validation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/api.wordpress.org/public_html/events/1.0/index.php

    r14998 r15016  
    195195        foreach ( $must_be_strings as $field ) {
    196196                if ( isset( $_GET[ $field ] ) && ! is_scalar( $_GET[ $field ] ) ) {
    197                         header( $_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400 );
    198                         die( '{"error":"Bad request.","reason":"' . $field . ' must be of type string."}' );
     197                        send_bad_request( $field . ' must be of type string.' );
    199198                }
    200199        }
    201200
    202201        if ( ! empty( $_POST['location_data'] ) ) {
    203                 foreach ( $_POST['location_data'] as $field => $value ) {
     202                // phpcs:ignore WordPress.Security -- Public unauthenticated endpoint; the value is only type-checked here, never used or output.
     203                foreach ( $_POST['location_data'] as $value ) {
    204204                        if ( ! is_scalar( $value ) ) {
    205                                 header( $_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400 );
    206                                 die( '{"error":"Bad request.","reason":"' . $field . ' must be of type string."}' );
     205                                // The key is omitted from the message because it is unsanitized request input.
     206                                send_bad_request( 'location_data values must be of type string.' );
    207207                        }
    208208                }
    209209        }
     210}
     211
     212/**
     213 * Send a 400 Bad Request response and halt.
     214 *
     215 * The `Content-Type` is set explicitly, because the header that `send_response()` sets is only
     216 * reached on the success path, and PHP would otherwise default this body to `text/html`.
     217 *
     218 * `wp_json_encode()` is intentionally not used here; it is loaded by `bootstrap()`, which runs
     219 * after the request is validated.
     220 *
     221 * @param string $reason The reason the request was rejected. Must not contain any unescaped
     222 *                       request input.
     223 */
     224function send_bad_request( $reason ) {
     225        $body = array(
     226                'error'  => 'Bad request.',
     227                'reason' => $reason,
     228        );
     229
     230        http_response_code( 400 );
     231        header( 'Content-Type: application/json; charset=UTF-8' );
     232        header( 'X-Content-Type-Options: nosniff' );
     233
     234        // phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode -- No WP loaded.
     235        die( json_encode( $body ) );
    210236}
    211237
Note: See TracChangeset for help on using the changeset viewer.