Can't retrieve body params from PUT endpoint using formdata

I have one endpoint to create players, which is a PUT request to a certain route. While I was sending parameters via JSON, it was working fine, but now I need to upload a picture with data, so I switched to formdata format.

This is the function running in the endpoint:

    public function put(WP_REST_Request $request)
    {

        ['foto' = $file] = $request-get_file_params();

        if (!empty($file)) {
            if (!function_exists('media_handle_upload')) {
                require_once(ABSPATH . 'wp-admin/includes/image.php');
                require_once(ABSPATH . 'wp-admin/includes/file.php');
                require_once(ABSPATH . 'wp-admin/includes/media.php');
            }

            $attachmentId = media_handle_upload('foto', 0);
        }

        //Recebe os dados
        $genero = $request['genero'];
        $nome = $request['nome'];
        $apelido = $request['apelido'];
        $data_nascimento = $request['data-nascimento'];
        $turma = $request['class_id'];
        $avatar = $request['avatar'];
        $id_parent = $request['user_id'];

        //Criar player
        $playerId = wp_insert_post([
            'post_type' = 'player'
            'post_status' = 'publish',
            'post_title' = '',
            'post_author' = $id_parent,
            'meta_input' = [
                'genero' = $genero,
                'nome' = $nome,
                'apelido' = $apelido,
                'data-nascimento' = $data_nascimento,
                'avatar' = $avatar,
            ]
        ]);

        if (is_wp_error($playerId)) {
            return $this-error([
                'status' = 'error',
                'message' = 'Não foi possível criar o jogador'
            ]);
        }

        // ...
        return $this-response([
            'status' = 'success',
            'message' = 'player cadastrado',
            'id' = $playerId,
            // next row is added for testing purpose
            'body_params' = $request-get_body_params(),

        ], 201);
    }

This runs in rest_api_init hook:

// ...
        register_rest_route(zw/v1, players, [
                    'methods' = PUT,
                    'callback' = [$playersApi, put],
                    'permission_callback' = [$playersApi, 'permissionCallback']
                ]);

When I use PUT method, body_params returns as empty array. Switching to POST method it works as expected. But I would like to keep semantics of the API, so what do I have to do to make PUT request read the body as formdata?

Topic endpoints rest-api plugin-development Wordpress

Category Web


This is because PUT requests don't have body parameters, that's not how PUT works. PUT doesn't quite do what you thought it did, and can only be used to upload a file from a client.

Your endpoint is incompatible with PUT as a request type because you're providing parameters as key value pairs, and that is not possible with PUT:

According to the HTML standard, you can not. The only valid values for the method attribute are get and post, corresponding to the GET and POST HTTP methods. is invalid HTML and will be treated like , i.e. send a GET request.

Likewise:

XHTML 1.x forms only support GET and POST. GET and POST are the only allowed values for the "method" attribute.


As for WordPress, it doesn't handle PUT and treats it as an alias of POST along with PATCH, so while its handling is technically correct, it's only by accident.

Now this doesn't prevent PHP from using it as a file upload mechanism, but that is the only thing it can be used for:

https://www.php.net/manual/en/features.file-upload.put-method.php

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.