Saturday, March 25, 2023

How to send HTTP POST Request with JSON Payload to REST API using Curl Command?

There are many ways to test your RESTful Web services developed using Spring MVC e.g. you can use RESTAssured for automation testing or you can use Postman to manually test your RESTful Web service but nothing beats the elegant, comfort, power, and simplicity of using curl command to test RESTful web service. It is my favorite tool to test any RESTful web service and I have used in past to test various aspect of Spring REST application e.g. testing headers, testing authentication and authorization, testing different content types like JSON and XML, testing cookies, and testing different HTTP methods to perform CRUD operations. 

I like curl command because I mostly work in Linux and it's readily available there, so I don't need to install any other tool just for testing RESTful APIs.  It also allows me to leverage my Linux expertise as I can create scripts to check if my RESTful web service is live and working and perform other stuff by writing shell scripts. 

I have summarized my testing techniques in earlier post about testing REST APIs using curl command but in this particular post I will talk about one of the common but initially hard test to carry out. 

In this article, you will learn how to post JSON data with curl command to test your Spring REST application. If you know curl command, you know that it's easy to send POST request as it allows you to specify content in the command line itself or load from the file using -d option. 

In general, if your JSON is small enough to fit into command line then you should directly write into shell otherwise you can always load that from a file, we'll look into both option in this article.




How to avoid "Unsupported Media type" while sending POST Request using Curl Command?

Many developers who are familiar with curl command specify the JSON data which needs to be send on POST command using -d option as shown below:

$ curl -i \
-H "Accept: application/json" \
-X POST 
-d '{"username":"root","password":"root"}'
https://localhost:8080/springdemo/rest/book

And this is where many developer make mistakes. In first look, the command look alright but if you run that it will fail by saying "Unsupported Media type" e.g.

HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 300

They fail to realize setting correct Content-Type, which resulted in this error. By default, -d sends the Content-Type as "application/x-www-form-urlencoded", which is not accepted on Spring's side and that's why you get this error. 

To avoid this, you need to send the correct content type by using the "Content-Type" header as shown below:

-H "Content-Type: application/json"

This will be accepted on the Spring side. Remember, Accept and Content-Type are two different headers. So, even though you are sending the same information in earlier example, it wasn't inside the correct header. The Accept header is used to indicate the media type client is expecting from server.




How to use Curl command to send HTTP Post Request with JSON data to Spring REST application

Now that you are aware of the common mistake many Java developer make while using curl command for sending JSON data as payload, it's time to revisit the correct curl command and understand it little bit better:

The right command is:

$ curl -X POST -H "Content-Type: application/json" -d '{"key":"val"}' URL

Here:
-X specify the HTTP method which is POST
-H is to add a header which is "Content-Type"
-d is to specify payload data, since JSON is enclosed in double quotes, you can use single quotes (') in Linux to enclose JSON data to directly specify in the command line. 
URL is the full URL of your Spring REST application e.g. https://localhost:8080/springdemo/

Here is one more version of same command for easier understanding:

$ curl -i \
-H "Content-Type: application/json" \
-X POST 
-d '{"username":"root","password":"root"}'
https://localhost:8080/springdemo/rest/book

The single quotes really work well in Linux to enclose JSON data, but if you are using curl on Windows then you need to escape those double quotes like

$ curl -i \
-H "Content-Type: application/json" \
-X POST 
-d "{\"username\":\"root\",\"password\":\"root\"}"
https://localhost:8080/springdemo/rest/book

This curl command is good if your JSON payload for POST method is small enough but if you have to send a JSON which is just more than a couple of line, it's better to store them in a file and attach that file as payload using --data option for curl command. Let's see an example of that. 




How to send POST Request with JSON Payload from File using Curl command in Linux

If you have stored your JSON data in a file called payload.json then you can POST that using following curl command:

$ curl -i \
-H "Content-Type: application/json" \
--data @payload.json
https://localhost:8080/springdemo/rest/book

This is much nicer because most of the JSON are really not that short and using file also allows you to avoid those escaping of double quotes around JSON data, particularly on Windows. In Linux, you can still get around using single quotes but if JSON is large you better use this option. 

You should also remember that you need to put the @before the filename to make it work, otherwise, curl will not include JSON data from your file.




Points to Note while Sending JSON Payload in POST command using Curl command

Now that you know how to send a POST request with JSON data to test a RESTful Web service using curl command in Linux and Windows, it's time to revise some of the stuff which you should know and remember to avoid wasting hours in painful debugging

1) Always specify the "Content-Type" header using -H option e.g. -H "Content-Type: application/json".

2) Remember that -d sends content type as "application/x-www-form-urlencoded", which is not accepted on Spring side if it is accepting "application/json"

3) Don't forget to enclose JSON data into single quotes in Linux e.g. -d 'json-data'.

4) Remember to escape double quotes in windows while writing JSON on the command line. 

5) Use --data option to POST JSON data from a file. 

6) Remember to specify @ before file name, otherwise curl will not take data from file. 

These are just some of the tips which you should already know if you are familiar with curl and Spring REST application, but if you want to learn more about curl, you can also always check these best Linux command line fundamentals courses to learn Linux and cURL better. 

How to POST JSON data with Curl Command to Test RESTful Web Service in Java and Spring?


That's all about how to POST JSON data using curl command to test a RESTful web service. It's not required that RESTful application is written Spring, it's just we have used for our example because Spring MVC provides the easiest way to develop RESTful web services in Java. If you are new in that domain, I suggest you to go through REST with Spring course to learn developing RESTful application in Java from scratch.

Other Spring and REST tutorials you may like:


Thanks for reading this article so far. If you like this tutorial about using cURL command to send JSON payload to a REST web services in Java and Spring then please share on Facebook and Twitter, I would really appreciate that. 

2 comments:

  1. Hello Deepak, just use the same command, if curl is supported then it will work, otherwise you can install git bash it comes with bash shell and Linux command line and you can run this command as it is on git bash. Or you can also use Cygwin to run Linux command on Windows. My favorite is gitbash though as you can use it as git client as well.

    ReplyDelete