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.
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:
- How to set Accept Header on Spring RestTemplate Request?
- Top 5 Tools to test REST Web Services in Java
- Difference between REST and GraphQL Web Services?
- How to send POST request with JSON Payload using RestTemplate?
- Difference between SOAP and RESTful web services
- How to create RESTful API using Java and Spring
- Top 5 Courses to learn Swagger for REST API Testing
- How to create RESTFul Service using Restlet Framework
- Top 5 Courses to learn API Development and Design
- Top 5 Courses to learn SoapUI for REST API Testing
- Top 5 Courses to learn RESTful Web services with Spring
- Difference between JAX-RS, Restlet, RESTEasy and Jersey
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.
How would you do in Windows
ReplyDeleteHello 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