Sending POST, PUT, and PATCH Requests with Fetch API and VueJS
Part 2 of 4 in Using Fetch API with VueJSIn the last tutorial, we covered the differences between the Fetch API and Axios when sending a GET request. Let’s take it up another notch and send POST, PUT, and PATCH requests with the Fetch API and compare how these methods operate compared to an Axios request.
If you want to jump ahead and see the answer, check out the Github repo for this component here. You can see the differences right away. If you want to see how this works, keep reading!
Step 1: Overview
For this tutorial, we are going to send data to an API endpoint. We are going to use our publicly available ROAST API. I’ll walk through how we send data to an endpoint, apply authorization (these methods require authorization 99.9% of the time) and the differences between the Fetch API and Axios. The endpoint we will be using will be for adding a Brew Method (https://api.roastandbrew.coffee/api/v1/brew-methods) and one for Updating a Brew Method (https://api.roastandbrew.coffee/v1/brew-methods/{methodID}).
Not to disappoint, but these are protected endpoints and will not create data unless a valid access token is provided. Most endpoints implemented through POST, PUT, and PATCH are protected. These endpoints serve as great examples though and will show in detail the differences between the Fetch API and Axios.
Step 2: Creating Your POST API Request
To show the differences between the Fetch API and Axios, I created the same request twice, one with each tool. The POST requests below are:
Fetch API POST Request
fetch( 'https://api.roastandbrew.coffee/api/v1/brew-methods', {
method: 'POST',
headers: {
'Authorization': 'Bearer '+this.token,
'Accept': 'application/json',
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify( this.form )
} )
.then( function( response ){
if( response.status != 201 ){
this.fetchError = response.status;
}else{
response.json().then( function( data ){
this.fetchResponse = data;
}.bind(this));
}
}.bind(this));
And with Axios:
Axios POST Request
axios.post('https://api.roastandbrew.coffee/api/v1/brew-methods', this.form, {
headers: {
'Authorization': 'Bearer '+this.token,
}
} )
.then( function( response ){
this.axiosResponse = response.data;
}.bind(this))
.catch( function( error ){
this.axiosError = error;
}.bind(this));
Just at first glance you can see that the Fetch API requires a little more configuration than Axios out of the box. Right away I start to think that if we are using the Fetch API in our application, we will have to abstract some of these settings to an object so the code is a little cleaner. Let’s dive into the method signatures.
Step 3: Differences Between Fetch API and Axios POST Request
Right away, the two methods look different. The Fetch API is much more complex. This is because Axios provides some standard defaults for what to send and what to expect from the server. As I mentioned above, I think that in order to keep using the Fetch API, we will have to make an easily configurable settings module ourselves. Otherwise, we will end up with what looks like spaghetti code everywhere and more possibilities for errors.
Before even diving into the method signature, I had to include
import axios from 'axios'
In order to use Axios. While on the topic of Axios, let’s start with the Axios POST method:
axios.post('https://api.roastandbrew.coffee/api/v1/brew-methods', this.form, {
headers: {
'Authorization': 'Bearer '+this.token,
}
} )
I love how Axios provides an explicit .post()
method that allows you to pass parameters directly to it. I find this to be super easy to read and explicit. Axios does have a signature similar to the Fetch API where you can pass the method
as an option, but honestly, I never use it.
The POST method accepts the URL
as the first parameter. This is the endpoint we will be hitting with data. The second parameter, this.form
is the data we are sending to the endpoint. For now, this will just be JSON. When we get to files, it will be slightly different to send. The third parameter is any other options we wish to send with the request. In this case, we added an Authorization: Bearer {token}
header. Like I mentioned before, these methods usually require some sort of authorization to run. If you want to see this component in full where this.form
and this.token
are defined, check out the GitHub repo.
That’s it for the Axios request! We can now send this request to our endpoint and it will include the data and proper authorization.
Moving on to the Fetch API, we start to really see differences with the methods:
fetch( 'https://api.roastandbrew.coffee/api/v1/brew-methods', {
method: 'POST',
headers: {
'Authorization': 'Bearer '+this.token,
'Accept': 'application/json',
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify( this.form )
} )
Like the Axios POST request, the first parameter is the URL of the endpoint we are sending data to. After that, everything changes. The second parameter in this request is an object that configures everything about the request. First, we define the method as a POST
request in the settings using method: 'POST'
. This is different from using Axios where the method is explicitly available with the .post()
method.
Next, we define our headers. The first header we include is the Authorization: Bearer {this.token}
header similar to Axios. Next, using our API, we have to define the Accept
and Content-Type
headers. Axios has these pre-defined, but the Fetch API does not. Your API may differ, but for standard JSON APIs, this is what is required. When we discuss uploading files, this will be different since we will be sending everything as form data.
Finally, we have our POST body which is defined as body: JSON.stringify( this.form )
. Unlike Axios where you can pass JSON as the second parameter, you have to define the body
explicitly.
Step 4: Handling a POST Request Response Using the Fetch API
Similar to how we handle a GET request response, we handle our responses depending on the status:
if( response.status != 201 ){
this.fetchError = response.status;
}else{
response.json().then( function( data ){
this.fetchResponse = data;
}.bind(this));
}
The only difference is POST requests should return a 201
response code instead of a 200
.
Step 5: Sending PUT and PATCH requests Using the Fetch API
Both of these requests have the exact same signature as a POST
request when using the Fetch API. The only difference is you have to change the method:
setting in your request to either PUT
or PATCH
. With Axios, you’d call either axios.put()
or axios.patch()
.
Upon response, the status code may be different as well such as an empty response which would be a 204
that you’d have to check for.
Conclusion
After running through the examples with both Fetch API and Axios, I’m definitely seeing the need to make some sort of standardized settings if I want to continue with the Fetch API. Axios makes this extremely easy using their configuration set up. I do like the idea of removing another unnecessary library if I don’t need it, but I love Axios and honestly it will be hard to switch. I’ll run through a few more examples with the Fetch API and see what other differences come up.