Introduction
As a part of End to End REST Assured Tutorial, in this post, we will learn to why and how to set the Content-Type header in Rest Assured for a request.
Content-Type is a header that indicates the media type or MIME( Multipurpose Internet Mail Extensions ) type or type of a file. When we hit any POST or PUT API requests we may need to pass a payload. That payload can be in any supported format by API such as XML, JSON, etc. We need to use the Content-Type header to let the server know the format of the payload for a request which will be sent.
Similarly, Content-Type for response indicates the format of the response returned. It is not mandatory that the Content-Type of request and response should be the same.
Prerequisite
I have used below dependency of Rest Assured library for this post:-
io.rest-assured rest-assured 4.3.1 test
Why we may need to set Content-Type explicitly for a request?
Postman tool automatically adds a Content-Type header based on the request body we select. For example, if select request body format as JSON then Postman will add automatically a header named “Content-Type” with value as “application/json“. This does not happen automatically in Rest Assured and you may get an unexpected response as a server may not identify the format of payload.
Let’s see an example where we are not setting up Content-Type explicitly. We are passing a payload which is in a JSON format.
package RestAssuredBasicConcepts; import org.testng.annotations.Test; import io.restassured.RestAssured; public class SetContentTypeForRequest { @Test public void WIthoutSettingContentType() { RestAssured .given() .log() .all() .body("{\r\n" + " \"firstname\" : \"Jim\",\r\n" + " \"lastname\" : \"Brown\",\r\n" + " \"totalprice\" : 111,\r\n" + " \"depositpaid\" : true,\r\n" + " \"bookingdates\" : {\r\n" + " \"checkin\" : \"2018-01-01\",\r\n" + " \"checkout\" : \"2019-01-01\"\r\n" + " },\r\n" + " \"additionalneeds\" : \"Breakfast\"\r\n" + "}") .post("https://restful-booker.herokuapp.com/booking") .then() .log() .all(); } }
Output
[RemoteTestNG] detected TestNG version 7.0.1 Request method: POST Request URI: https://restful-booker.herokuapp.com/booking Proxy:Request params: Query params: Form params: Path params: Headers: Accept=*/* Content-Type=text/plain; charset=ISO-8859-1 Cookies: Multiparts: Body: { "firstname" : "Jim", "lastname" : "Brown", "totalprice" : 111, "depositpaid" : true, "bookingdates" : { "checkin" : "2018-01-01", "checkout" : "2019-01-01" }, "additionalneeds" : "Breakfast" } HTTP/1.1 500 Internal Server Error Server: Cowboy Connection: keep-alive X-Powered-By: Express Content-Type: text/plain; charset=utf-8 Content-Length: 21 Etag: W/"15-/6VXivhc2MKdLfIkLcUE47K6aH0" Date: Tue, 29 Sep 2020 07:42:56 GMT Via: 1.1 vegur Internal Server Error PASSED: WIthoutSettingContentType =============================================== Default test Tests run: 1, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 1, Passes: 1, Failures: 0, Skips: 0 ===============================================
We are passing a JSON payload to request but observe in output that it takes Content-Type as “text/plain” and return a response as “Internal server error“. Sever could not understand the correct format of the request payload and failed. This is the reason we should set Content-Type for a request properly.
Adding Content-Type to a request in Rest Assured
As Content-Type is a header we can pass it as a key-value pair using methods discussed here. An example is as below:-
package RestAssuredBasicConcepts; import org.testng.annotations.Test; import io.restassured.RestAssured; public class SetContentTypeForRequest { @Test public void settingContentTypeAsHeader() { RestAssured .given() .log() .all() .header("Content-Type", "application/json") .body("{\r\n" + " \"firstname\" : \"Jim\",\r\n" + " \"lastname\" : \"Brown\",\r\n" + " \"totalprice\" : 111,\r\n" + " \"depositpaid\" : true,\r\n" + " \"bookingdates\" : {\r\n" + " \"checkin\" : \"2018-01-01\",\r\n" + " \"checkout\" : \"2019-01-01\"\r\n" + " },\r\n" + " \"additionalneeds\" : \"Breakfast\"\r\n" + "}") .post("https://restful-booker.herokuapp.com/booking") .then() .log() .all(); } }
Output
[RemoteTestNG] detected TestNG version 7.0.1 Request method: POST Request URI: https://restful-booker.herokuapp.com/booking Proxy:Request params: Query params: Form params: Path params: Headers: Accept=*/* Content-Type=application/json; charset=UTF-8 Cookies: Multiparts: Body: { "firstname": "Jim", "lastname": "Brown", "totalprice": 111, "depositpaid": true, "bookingdates": { "checkin": "2018-01-01", "checkout": "2019-01-01" }, "additionalneeds": "Breakfast" } HTTP/1.1 200 OK Server: Cowboy Connection: keep-alive X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 195 Etag: W/"c3-E5R+AIhAHdRg+t7MhfO18uLvLAw" Date: Tue, 29 Sep 2020 07:52:19 GMT Via: 1.1 vegur { "bookingid": 21, "booking": { "firstname": "Jim", "lastname": "Brown", "totalprice": 111, "depositpaid": true, "bookingdates": { "checkin": "2018-01-01", "checkout": "2019-01-01" }, "additionalneeds": "Breakfast" } } PASSED: WIthoutSettingContentType =============================================== Default test Tests run: 1, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 1, Passes: 1, Failures: 0, Skips: 0 ===============================================
In the above approach, if you misspell the header name and its expected values then you will get an unexpected response. So to overcome that RequestSpecification class provided a below method:-
RequestSpecification contentType(ContentType contentType);
ContentType is an enum which contains members as “ANY”, “JSON”, “XML” etc. If I want to set Content -Type as JSON then I will use contentType() method as below:-
contentType(ContentType.JSON)
A complete example is as below:-
package RestAssuredBasicConcepts; import org.testng.annotations.Test; import io.restassured.RestAssured; import io.restassured.http.ContentType; public class SetContentTypeForRequest { @Test public void settingContentTypeAsContentType() { RestAssured .given() .log() .all() .contentType(ContentType.JSON) .body("{\r\n" + " \"firstname\" : \"Jim\",\r\n" + " \"lastname\" : \"Brown\",\r\n" + " \"totalprice\" : 111,\r\n" + " \"depositpaid\" : true,\r\n" + " \"bookingdates\" : {\r\n" + " \"checkin\" : \"2018-01-01\",\r\n" + " \"checkout\" : \"2019-01-01\"\r\n" + " },\r\n" + " \"additionalneeds\" : \"Breakfast\"\r\n" + "}") .post("https://restful-booker.herokuapp.com/booking") .then() .log() .all(); } }
Output
[RemoteTestNG] detected TestNG version 7.0.1 Request method: POST Request URI: https://restful-booker.herokuapp.com/booking Proxy:Request params: Query params: Form params: Path params: Headers: Accept=*/* Content-Type=application/json; charset=UTF-8 Cookies: Multiparts: Body: { "firstname": "Jim", "lastname": "Brown", "totalprice": 111, "depositpaid": true, "bookingdates": { "checkin": "2018-01-01", "checkout": "2019-01-01" }, "additionalneeds": "Breakfast" } HTTP/1.1 200 OK Server: Cowboy Connection: keep-alive X-Powered-By: Express Content-Type: application/json; charset=utf-8 Content-Length: 195 Etag: W/"c3-Hgn0HOW7t3wbXoNXHOll0aSCOGo" Date: Tue, 29 Sep 2020 07:58:29 GMT Via: 1.1 vegur { "bookingid": 12, "booking": { "firstname": "Jim", "lastname": "Brown", "totalprice": 111, "depositpaid": true, "bookingdates": { "checkin": "2018-01-01", "checkout": "2019-01-01" }, "additionalneeds": "Breakfast" } } PASSED: settingContentTypeAsContentType =============================================== Default test Tests run: 1, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 1, Passes: 1, Failures: 0, Skips: 0 ===============================================
You can download/clone the above sample project from here.
You can subscribe to my YouTube channel RetargetCommon to learn from video tutorials.
If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning
Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.
Many other topics you can navigate through the menu.
I have simple test using rest assured as below.
Case1: If I pass json string as below, it works fine.
@Test
public void dummyTest throws Exception {
String newUserEmail = “postOrder” + UUID.randomUUID() + “@gmail.com”;
String json = “{\n” +
” \”name\”: \”Marisa\”,\n” +
” \”birthday\”: \”1997-10-06\”,\n” +
” \”title\”: \”Dr.\”,\n” +
” \”email\”: \”postOrder26@gmail.com\”,\n” +
” },\n”
given()
.baseUri(“my_request_url”)
.header(“Content-Type”, “application/json”)
.body(json)
.when()
.post()
.then()
.log().all();
}
Above returns 200 response.
***************************************************************************************************
But If I write my test as below , passing email as variable, returns 500
@Test
public void dummyTest throws Exception {
String newUserEmail = “postOrder” + UUID.randomUUID() + “@gmail.com”;
String json = “{\n” +
” \”name\”: \”Marisa\”,\n” +
” \”birthday\”: \”1997-10-06\”,\n” +
” \”title\”: \”Dr.\”,\n” +
” \”email\”: \””+newUserEmail+”\”,\n” +
” },\n”
given()
.baseUri(“my_request_url”)
.header(“Content-Type”, “application/json”)
.body(json)
.when()
.post()
.then()
.log().all();
}
**********************************************************************************************************************************
I get 500 error response
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Mon, 16 Aug 2021 17:05:36 GMT
Server: Apache
Cache-Control: no-cache, private
X-Cache: Error from cloudfront
Via: 1.1 871dedfc10f4428aa2412b6f788b791a.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: ZRH50-C1
X-Amz-Cf-Id: xGkO8cJGV0Pq7wAx71YyglWzQNdZzooohqZLZBHkC54iZgiNhGmpEA==
/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: https://yuilibrary.com/license/ */
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:”;}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
html { background: #eee; padding: 10px }
img { border: 0; }
#sf-resetcontent { width:970px; margin:0 auto; }
body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, “Helvetica Neue”, Arial, sans-serif; margin: 0; }
.container { margin: 30px; max-width: 600px; }
h1 { color: #dc3545; font-size: 24px; }