0

I am trying to make an Axios DELETE request to my Express server. I've looked through every discussion and each solution does not work. Documentation didn't really explain the delete part very well.

React Action Creator

export const deleteDbPost = (postId) => async(dispatch) => {
    console.log(postId);
    const response = await axios.delete(`http://localhost:8000/api/delete/post/${postId}`,
        { data: postId },
        {
            headers: {
                "Authorization": localStorage.getItem("access_token") !== null ? `Bearer ` + localStorage.getItem("access_token") : null,
                "Content-Type": "application/json"
            }
        }
    );
    console.log(response);
    dispatch({ type: DELETE_DB_POST, payload: response.data });
    history.push('/posts');
}

Basically the Express server sees the request, but the body or data is not present.

Express server to handle request

router.delete('/api/delete/post/:pid', (res, req, next) => {
    console.log(req.body);
    const post_id = req.body.pid;
    pool.query(`DELETE FROM posts
                WHERE pid=$1`, [post_id], (q_err, q_res) => {
                    if (q_err) return next(q_err); // Note: Why do we use next here??                    res.json(q_res.rows);
                    console.log(q_err);
                    res.json(q_res.rows);
                })
})

From the Express server code, when I do console.log(req.body), I get "Cannot read property of '...' of undefined". From my research, it appears only GET, PUT, PATCH allows for the body in the request. But I've found other solutions that allowed for this to work, however, I have no luck in this. Any help would be greatly appreciated! Thanks.

Valeed Anjum
  • 447
  • 1
  • 5
  • 17
jeff
  • 490
  • 1
  • 6
  • 21
  • You have `data` and `headers` in two separate objects. The one with `headers` is passed as the third argument which means it gets ignored, which means the `Content-Type` doesn't get properly set, which means the body can't be parsed on the server. Put `data` and `headers` in the same object, that you pass as the second argument. – Lennholm May 27 '20 at 02:41

3 Answers3

0

Since it's a delete request, req.body will show undefined. Instead you will have to use req.params

router.delete('/api/delete/post/:pid', (res, req, next) => {
    console.log(req.params); //<----Here
    const post_id = req.params.pid; //<-----Here
    pool.query(`DELETE FROM posts
                WHERE pid=$1`, [post_id], (q_err, q_res) => {
                    if (q_err) return next(q_err); // Note: Why do we use next here??                    res.json(q_res.rows);
                    console.log(q_err);
                    res.json(q_res.rows);
                })
})
Nikhil G
  • 2,096
  • 14
  • 18
  • It might be worth pointing out why one needs to use params instead of a body (HTTP "request entity") as described here https://stackoverflow.com/a/10015724/623316 and https://tools.ietf.org/html/rfc7231#section-4.3.5. I.e. an entity in a DELETE request is meaningless. – Jon Wolski May 27 '20 at 02:45
  • Thanks for the response! I tried that, but I still get undefined in the console.log(req.params) :( – jeff May 27 '20 at 02:46
0

According to your code, you have at least two solutions to this problem, in your delete route handler:

router.delete('/api/delete/post/:pid', (req, res, next) => {
console.log(req.params.pid); //your route params passed in http delete method
console.log(req.body.data); //your current value for pid
//const post_id = req.body.pid; <-- undefined as you don't passed this value
pool.query(`DELETE FROM posts
                WHERE pid=$1`, [post_id], (q_err, q_res) => {
                    if (q_err) return next(q_err); // Note: Why do we use next here??                    res.json(q_res.rows);
                    console.log(q_err);
                    res.json(q_res.rows);
                })
})

Also would like to point out to change your error handler for a more straightforward way to return the error.

if (q_err) {
   //handle the q_err to not expose sensible data
   return req.status(500).json(q_err.message); //return some  meaningful error msg
}
res.status(200).json(q_res.rows);
//res.status(204).end() //no body response
//also when doing a delete you should not send a body.

Evidence of a delete with body

* Preparing request to http://localhost:3002/users/5ecddf90a544a74ef349c663
* Using libcurl/7.67.0 OpenSSL/1.1.1d zlib/1.2.11 nghttp2/1.29.0
* Current time is 2020-05-27T03:34:39.726Z
* Disable timeout
* Enable automatic URL encoding
* Enable SSL validation
* Enable cookie sending with jar of 4 cookies
* Hostname in DNS cache was stale, zapped
*   Trying 127.0.0.1:3002...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3002 (#6)

> DELETE /users/5ecddf90a544a74ef349c663 HTTP/1.1
> Host: localhost:3002
> User-Agent: insomnia/7.1.1
> Content-Type: application/json
> Accept: */*
> Content-Length: 104

|     {
|       "name": "eu1sad2",
|       "login": "adminsadad",
|       "password": "1lkajdhasdadsa0987"
|     }

* upload completely sent off: 104 out of 104 bytes
* Mark bundle as not supporting multiuse

< HTTP/1.1 204 No Content
< Access-Control-Allow-Origin: *
< Date: Wed, 27 May 2020 03:34:39 GMT
< Connection: keep-alive


* Connection #6 to host localhost left intact

A delete without body, just for compare:

* Preparing request to http://localhost:3002/users/5ecddff4a544a74ef349c664
* Using libcurl/7.67.0 OpenSSL/1.1.1d zlib/1.2.11 nghttp2/1.29.0
* Current time is 2020-05-27T03:35:47.358Z
* Disable timeout
* Enable automatic URL encoding
* Enable SSL validation
* Enable cookie sending with jar of 4 cookies
* Connection 7 seems to be dead!
* Closing connection 7
*   Trying 127.0.0.1:3002...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3002 (#8)

> DELETE /users/5ecddff4a544a74ef349c664 HTTP/1.1
> Host: localhost:3002
> User-Agent: insomnia/7.1.1
> Content-Type: application/json
> Accept: */*
> Content-Length: 0

* Mark bundle as not supporting multiuse

< HTTP/1.1 204 No Content
< Access-Control-Allow-Origin: *
< Date: Wed, 27 May 2020 03:35:47 GMT
< Connection: keep-alive


* Connection #8 to host localhost left intact
Danizavtz
  • 3,166
  • 4
  • 24
  • 25
  • Hey thanks for the response! I'm not getting a console.log print statement from this... I'm not too sure why. I have tried what you wrote down. – jeff May 27 '20 at 02:55
  • In your implementation you have to rename the params for `(req, res, next)`, currently you have `(res, req, next)` – Danizavtz May 27 '20 at 02:57
  • Wow.. How did I not see that... You're a miracle worker!! Thanks a bunch. I do have one more question if you don't mind me asking.. Why wouldn't using req.body.pid work? I thought I passed that in from the React Action Creator – jeff May 27 '20 at 03:03
  • Yes, it can work that way, if you change the second parameter from your delete from: ` { data: postId }` to: ` { pid: postId }` – Danizavtz May 27 '20 at 03:06
  • I had that previously, but it didn't work.. So I was reading countless posts which said DELETE requests don't have a body, so you have to specify a data object or something.. not too sure :S – jeff May 27 '20 at 03:09
  • In fact I never write a delete with information in body, Maybe its a limitation from your lib to handle requests, I can test that. – Danizavtz May 27 '20 at 03:11
  • Just updated my answer with an evidence of a delete with body. – Danizavtz May 27 '20 at 03:43
0

At the current time the axios.delete method only has 2 parameters.

  1. url
  2. Request object

In order to send a body withing the delete you have to pass the data inside the request object. Like so:

export const deleteDbPost = (postId) => async(dispatch) => {
    const response = await axios.delete(`http://localhost:8000/api/delete/post/${postId}`,
        {
            data: { postId },
            headers: // ...
        }
    );
    // ...
}
jogarcia
  • 2,327
  • 2
  • 19
  • 34