DEV Community

loading...
Cover image for Axios PUT Verb

Axios PUT Verb

Tim Myers
Sometimes when I’m alone in my room I write software... it’s for fun. I’m a father but I’m not like all up in your face about it. | 🤘 Metal 🤘| Pro-Am Chef
・3 min read

Axios PUT Verb And Why I Suck

So this is one of those posts where I had such a hard time I just wanted to document it so I would have a note for myself in the future.

Here's the issue I was having:

We have a project that uses React for the frontend and Azure Functions for the API. One of our Azure functions for submitting an order required, GET, PUT, POST, DELETE.

I got the function setup and all of the backend code was working using Postman to submit requests to the API.

When I started working on the front end everything was working except for the PUT verb.

The DELETE verb code looked like this:

const handleOrderDelete = async (orderId) => {
  const token = await getTokenSilently()
  var response = axios.delete(`http:localhost:3000/${orderId}`, {
      headers: {
          Authorization: `Bearer ${token}`,
          'content-type': 'application/json',
          'x-functions-key': "AZURE FUNCTION KEY HERE",
      },
  })
  if (response.statusCode === 200) {
      console.log(response)
  } else {
      console.error(response)
  }
}
Enter fullscreen mode Exit fullscreen mode

The PUT verb code looked like this:

const handleOrderEdit = async (orderId) => {
  const token = await getTokenSilently()
  var response = axios.put(`http:localhost:3000/${orderId}`, {
      headers: {
          Authorization: `Bearer ${token}`,
          'content-type': 'application/json',
          'x-functions-key': "AZURE FUNCTION KEY HERE",
      },
  })
  if (response.statusCode === 200) {
      console.log(response)
  } else {
      console.error(response)
  }
}
Enter fullscreen mode Exit fullscreen mode

Now at this point it's important to note that I copied the handleOrderEdit code from the handleOrderDelete code. They are VERY similar, the only main difference being the .put and .delete verbs themselves.

Now if you're astute and you are familiar with Axios you may already see the issue. If not see if you can figure it out.

So the DELETE was working, but when I ran the PUT I was getting a 401 on the Network tab in chrome devtools. In my C# console I was getting the error, NO TOKEN. ERROR.

When I looked at the request payload I saw that I had a token, "Bearer 8df7saf8d7sa8f9dsa7f89saf6798saf" or whatever. Most importantly my breakpoint I set in Visual Studio right on the opening bracket of the PUT method was not being hit.

I replaced the axios.put call with a fetch call since they use a similar API. I had narrowed my search down to some issue with axios at this point because it was working in Postman.

I added the fetch like so:

fetch(`http://localhost:3000/${orderId}`, {
            headers: {
                Authorization: `Bearer ${token}`,
                'content-type': 'application/json',
                'x-functions-key': 'AZURE FUNCTION KEY HERE',
            },
        })
Enter fullscreen mode Exit fullscreen mode

and it worked just fine. I started looking a bit closer and I noticed something. When I submitted my request with axios the Bearer token was in the Payload, not in the Request Header. Hmm.

So, to make a long story short, (too late amirite???), I didn't realize that the PUT verb requires a body. We're not sending a body because all we're doing is setting the order back to a different status but we're using the PUT because all of the other verbs are being used.

Typically you would ALWAYS send a body with a PUT because you're updating a record and you need to send the information your replacing. Ours is a unique usecase and since we're sending the orderId in the url then we didn't need to send a body.

The code that fixed this whole thing is:

 const handleOrderSign = async (orderId) => {
        const token = await getTokenSilently()
        var response = axios.put(
            `${api.order.url}/${orderId}`,
            {orderId}, // < -- this
            {
                headers: {
                    Authorization: `Bearer ${token}`,
                    'content-type': 'application/json',
                    'x-functions-key': api.order.key,
                },
            }
        )
        if (response.statusCode === 200) {
            console.log(response)
        } else {
            console.error(response)
        }
    }
Enter fullscreen mode Exit fullscreen mode

Even though I don't need to send a body I'm sending the orderId in the body just so I better conform to the axios standard.

So this is either one of those things that everyone knows and I'm just slow on the uptake, or this is something that happened because we're not using the tool the way it was intended, or it's a lack of documentation on axios' side.

Anyway,

Thanks for reading and that's all y'all.

Discussion (9)

Collapse
Sloan, the sloth mascot
Comment deleted
Collapse
denvercoder profile image
Tim Myers Author • Edited

First of all I said the code is very similar. Meaning that my two code blocks are exactly the same except for

axios.put(

axios.delete(

But thank you SO very much for explaining to me that .put will send an HTTP PUT and .delete will perform an HTTP DELETE.

I really appreciate the fact that you explain basic principles to someone that has been writing software since 1986.

Collapse
Sloan, the sloth mascot
Comment deleted
denvercoder profile image
Tim Myers Author

It’s just really shitty when you break down basic concepts to someone that took the time to write a post.

I clearly say that I copy/pasted the two methods and that they are identical except for the line where the verb is. 🤷🏻‍♂️

And then you start in with:

.put() is for an HTTP PUT.

You would think that maybe you would give someone the benefit of the doubt and not just assume that everyone is a moron and so far beneath you that you have to explain basic concepts to them.

Maybe just assume that everyone knows everything that you know. 🤷🏻‍♂️

😏

Collapse
denvercoder profile image
Tim Myers Author

I know exactly that DELETE is supposed to delete a resource. I mentioned in the article that I was probably not using it correctly but we don't have a choice. I AM deleting a resource for the user but I'm just moving it from a status of 'submitted' to a status of 'rejected'.

I had to obfuscate a lot of the details of what I'm doing because I work for a healthcare company and I can just be dropping IP on dev.to.

Collapse
egeriis profile image
Ronni Egeriis Persson

It is a good example of why it's important for APIs to have the same argument, when it might be expected by the consumer.

While it's unlikely that you'll send a request body with a GET or a DELETE request and that makes it understandable that those are omitted, the question is if there might be an even better way to construct the Axios API so it doesn't lean into issues like these.

Same principles apply to application code.

Collapse
murkrage profile image
Mike Ekkel

It was my understanding that the body isn't necessarily required but it is common for the PUT request to have one. Putting that aside, a different fix for your problem would be to nullify the body:

const handleOrderSign = async (orderId) => {
        const token = await getTokenSilently()
        var response = axios.put(
            `${api.order.url}/${orderId}`,
            null,
            {
                headers: {
                    Authorization: `Bearer ${token}`,
                    'content-type': 'application/json',
                    'x-functions-key': api.order.key,
                },
            }
        )
        if (response.statusCode === 200) {
            console.log(response)
        } else {
            console.error(response)
        }
    }
Enter fullscreen mode Exit fullscreen mode

Mostly because axios needs to have that parameter set. Alternatively you could use the request config instead of using the .put() method.

Collapse
tqbit profile image
tq-bit

I feel you. You might not believe it, but I ran into pretty much the same fail today as well (token somehow ended up in the data - prop, wtf was I thinking)

My lesson learned here (hopefully) was:

  • Create axios instances in separate files and export them.
  • Explicitly define headers, http-method and data in a config object
// ... some async function code
const config = {
 url: 'https://my-url.com', 
 method: 'get',
 headers: {/* ... */},
 data: JSON.stringify({/* ... */})
}

const response = await axios(config)
// ... some more function code
Enter fullscreen mode Exit fullscreen mode
Collapse
filatovv profile image
Yuri Filatov

Thank you!