Java Guides
In this article, we will learn the frequently used HTTP methods in building RESTful APIs.
REST APIs enable you to develop any kind of web application having all possible CRUD (create, retrieve, update, delete) operations. REST guidelines suggest using a specific HTTP method on a particular type of call made to the server.
Let’s learn about HTTP methods and their role in client-server communication over HTTP.
HTTP GET Method
Use GET requests to retrieve resource representation/information only – and not to modify it in any way. As GET requests do not change the state of the resource, these are said to be safe methods. Additionally, GET APIs should be idempotent, which means that making multiple identical requests must produce the same result every time until another API (POST or PUT) has changed the state of the resource on the server.
If the address is successfully received (error-free), GET returns a JSON or XML representation in combination with the HTTP status code 200 (OK). In case of an error, the code 404 (NOT FOUND) or 400 (BAD REQUEST) is usually returned.
Examples for GET request URI’s:
HTTP GET — http://www.usermanagement/api/users/me — Get logged in user profile
HTTP GET — http://www.usermanagement/api/users//profile — Get user profile by username
HTTP GET — http://www.usermanagement/api/users//posts — Get posts created by user
HTTP GET — http://www.usermanagement/api/users//albums — Get albums created by user
http://www.usermanagement/api/users/checkUsernameAvailability — Check if username is available to register
http://www.usermanagement/api/users/checkEmailAvailability — Check if email is available to register
HTTP POST Method
The HTTP POST request is most commonly used to create new resources. When talking strictly in terms of REST, POST methods are used to create a new resource into the collection of resources.
Upon successful creation, an HTTP code 201 is returned, and the address of the created resource is also transmitted in the ‘Location’ header.
Here are some examples for HTTP POST requests:
HTTP POST — http://www.domain/api/users — Create User
HTTP POST — http://www.domain/api/posts — Create Post
HTTP POST — http://www.domain/api/posts//comments — Create new comment for post with >
HTTP PUT Method
Use PUT APIs primarily to update existing resource (if the resource does not exist, then API may decide to create a new resource or not). If a new resource has been created by the PUT API, the origin server MUST inform the user agent via the HTTP response code 201 (Created) response and if an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
Here are some examples for HTTP Put requests:
HTTP PUT — http://www.domain/api/users/ — Update user
HTTP PUT — http://www.domain/api/posts/ — Update post by id
HTTP PUT — http://www.domain/api/posts//comments/ — Update comment by id if it belongs to post with >
The difference between the POST and PUT APIs can be observed in request URIs. POST requests are made on resource collections, whereas PUT requests are made on a single resource.
HTTP DELETE Method
Use DELETE APIs to delete resources (identified by the Request-URI).
A successful response of DELETE requests SHOULD be HTTP response code 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has been queued, or 204 (No Content) if the action has been performed but the response does not include an entity.
Here are some examples for HTTP Delete requests:
DELETE http://www.domain/api/users/ — Delete user
DELETE http://www.domain/api/posts/ — Delete post
DELETE http://www.domain/api/posts//comments/ — Delete comment by id if it belongs to post with >
HTTP PATCH Method
HTTP PATCH requests are to make partial updates on a resource. If you see PUT requests also modify a resource entity, so to make more clear – the PATCH method is the correct choice for partially updating an existing resource, and PUT should only be used if you’re replacing a resource in its entirety.
A sample patch request to update the email will be like this:
When to Use HTTP PUT and When HTTP PATCH?
When a client needs to replace an existing Resource entirely, they can use PUT. When they’re doing a partial update, they can use HTTP PATCH.
For instance, when updating a single field of the Resource, sending the complete Resource representation might be cumbersome and utilizes a lot of unnecessary bandwidth. In such cases, the semantics of PATCH make a lot more sense.
Another important aspect to consider here is idempotence; PUT is idempotent; PATCH can be, but isn’t required to. And, so – depending on the semantics of the operation we’re implementing, we can also choose one or the other based on this characteristic.
Summary of HTTP Methods
Conclusion
In this article, we have learned about commonly used HTTP methods in RESTful API with examples.
Learn how to develop REST API’s using the Jersey framework at https://www.javaguides.net/p/restful-tutorial.html
Learn how to develop REST API’s using JAX RS with RESTEasy framework at https://www.javaguides.net/2020/01/resteasy-crud-example-tutorial.html
Related REST Articles
- Overview of REST
- REST API — HTTP Methods
- REST API — HTTP Status Codes
- Advantages of REST
- REST API — REST Architectural Constraints
- REST API — REST Architectural Properties
- REST API — REST Architectural Elements
- Difference Between SOAP vs REST Web Services
- How to Identify REST Resources
- How to Design URL to REST Resource
- How to Assign HTTP methods to REST Resources
- How to Model JSON Representation Format
- What HTTP Status Code to Return
REST-assured HTTP POST and PUT Examples
Learn to make HTTP POST and PUT requests in automated tests with REST-assured. We will learn different ways to customize the request body, headers and authentication. Also, we will learn to verify the API responses.
Before going deeper, let’s start with a simple HTTP POST example to introduce the basic APIs involved in the tests. The following is a POST API and request body.
A typical API call with sending the request body, headers and verifying the response data is as follows:
@Test public void createUserWithCustomObject_thenSuccess() throws JSONException < given() .body(new User("lokesh", "admin@howtodoinjava.com")) .header(new Header("x-custom-header", "value")) .contentType("application/json") .when() .post("/users") .then() .statusCode(201) .body("id", notNullValue()) .body("name", equalTo("lokesh")) .body("email", equalTo("admin@howtodoinjava.com")); >
2. Attaching POST Request Body
REST-assured supports sending the request body in many ways. Some of the most used ways are building JSONObject, parsing a custom object or directly sending the request body from a file. We can imitate a form submission as well.
The JSONObject is from JSON-java library, and REST-assured internally supports it. JSON-java supports parsing JSON documents into Java objects and generating new JSON documents from the Java classes. It can also convert between JSON and XML, HTTP headers, Cookies, and CDL.
To build the JSONObject, we use its put() method similar to Map in Java that takes a key and value. The value can be anything primitives, objects, collections or even Maps. By passing Map and collection, we can build any nested JSON structure.
JSONObject requestParams = new JSONObject(); requestParams.put("name", "lokesh"); requestParams.put("email", "admin@howtodoinjava.com"); given() .body(requestParams.toString()) .contentType("application/json") .when() .post("/users") .then() .statusCode(equalTo(201));
We can pass a custom POJO to the body() method.
User user = new User("lokesh", "admin@howtodoinjava.com"); given() .body(user) .contentType("application/json") .when() .post("/users") .then() .statusCode(equalTo(201));
The User is a simple POJO without any annotation.
To customize the serialization and deserialization, REST-assured support object mappers from GSON, JAXB, Jackson, Faster Jackson and Eclipse Yasson (JSON-B). For example, we can use the Gson annotations in the POJO and then build a GsonObjectMapperFactory with GsonBuilder as follows:
@BeforeAll public static void setup() < baseURI = "https://ROOT_URL/"; RestAssured.config = RestAssuredConfig.config() .objectMapperConfig(objectMapperConfig().gsonObjectMapperFactory( new GsonObjectMapperFactory() < @Override public Gson create(Type type, String s) < return new GsonBuilder() .setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES) .create(); >> )); >
2.3. Submitting File or InputStream
The body() takes parameters of type java.io.File and InputStream . We can pass on a JSON document directly to the API request. It helps prevent the complexity of parsing the correct JSON document from a POJO. It is sometimes the preferred way among testers who technically are not very efficient.
given() .body(new File("createUser.json")) .contentType("application/json") .when() .post("/users") .then() .statusCode(equalTo(201));
3. Adding Request Headers and Query Params
Use accept() and contentType() methods to pass the media-type information.
given() .body(. ) .accept("application/json") .contentType("application/json") .
To send query parameters, use the queryParam() method.
given() .body(. ) .queryParam("access-token", "abcd") .
Passing the authentication information depends on the auth scheme supported by the API. REST-assured supports almost all kinds of authentications OAuth, OAuth2, headers and even form submissions. Use oauth2() for passing the OAuth2 authentication token.
given() .auth().preemptive().oauth2(accessToken) .
For adding auth using the headers, AuthFilter is preferred over regular filters or direct headers because AuthFilter is removed when doing given().auth().none() for testing unsecured APIs.
given(). filter((requestSpec, responseSpec, ctx) -> < requestSpec.header("AUTH", "TOKEN"); return ctx.next(requestSpec, responseSpec); >). when(). post("/api"). then(). statusCode(200);
5. Validating Response Status and Body
REST-assured uses functionally rich Hamcrest matchers for verifying the response data. We can verify anything in the response including status codes, headers, cookies, body and even response time.
//Verify status post("/api").then().assertThat().statusCode(200). post("/api").then().assertThat().statusLine(containsString("OK")). .. //Verify headers post("/api").then().assertThat().header("headerName", "headerValue"). .. post("/api").then().assertThat().headers("headerName1", containsString("value")). . //Verify body given() .body(requestParams.toString()) . .when() .post("/users") .then() . .body("id", notNullValue()) .body("name", equalTo("lokesh")) .body("gender", equalTo("male")) .body("status", equalTo("active")) .body("email", equalTo("admin@howtodoinjava.com")) . ; //Verify response time post("/api").then().time(lessThan(2000L)); post("/api").then().time(lessThan(2L), TimeUnit.SECONDS);
6. Logging and Extracting Response Data
Logging helps in printing useful information about requests and responses so we can debug the test if it does not behave as expected. Rest-assured supports all(), params(), body(), headers(), cookies(), method() and path() methods for logging the specific information, if needed.
- Use given().log() for building the RequestLoggingFilter used for logging the request data.
- Use then().log() for logging the response data.
given().log().all() //Log all request specification details given().log().body() //Log only the request body post("/api").then().log().all() //Log all response specification details post("/api").then().log().body() //Log only the request body
In case we want to log the details only if validation fails then we can use ifValidationFails() method.
given().log().ifValidationFails(). . then().log().ifValidationFails().
REST-assured supports getting the whole response body and even a part of the response document, as well. For getting a specific response part we can use JSON-Path syntax.
InputStream stream = post("/api").asInputStream(); byte[] byteArray = post("/api").asByteArray(); String json = post("/api").asString(); String . .post("/users") .then() . .extract().body().path("user.id");
In this tutorial, we learned to test the HTTP POST and PUT APIs using different techniques of sending the custom request body, headers, parameters and authentication tokens. we also learned to process the response data including logging, verifying, extracting and measuring time for performance testing.