# Http Methods and Status Codes

The HTTP specification includes a collection of methods that are used to interact with server-side resources. There are also HTTP method properties to consider, including whether a HTTP request is safe, idempotent, or cacheable.

| Method  | Safe | Idempotent | Cacheable              |
| ------- | ---- | ---------- | ---------------------- |
| GET     | ✔️   | ✔️         | ✔️                     |
| HEAD    | ✔️   | ✔️         | ✔️                     |
| OPTIONS | ✔️   | ✔️         | ❌                      |
| TRACE   | ✔️   | ✔️         | ❌                      |
| DELETE  |      | ✔️         | ❌ ,  invalidates cache |
| PUT     |      | ✔️         | ❌,  invalidates cache  |
| POST    |      |            | Sometimes              |
| PATCH   |      |            | Sometimes              |
| CONNECT |      |            | No                     |

### Method properties <a href="#method-properties" id="method-properties"></a>

HTTP requests have different properties and there are some important commonalities. Request methods can be safe, idempotent, and/or cacheable.

### Safe  <a href="#safe" id="safe"></a>

HTTP method that is safe will not have any effect on the state of the server, it can be thought of as one that is *read-only*.

The safe HTTP methods are: <mark style="color:purple;">GET, HEAD, OPTIONS,</mark> and <mark style="color:purple;">TRACE.</mark>

However, in practice, this is often not realistic because there is no guarantee that the server does not generate side effects because of the HTTP request.

For example, if each HTTP <mark style="color:purple;">GET</mark> request causes a publicly visible *“visitor counter”* to change, then technically, the state of the server has changed. Importantly, the HTTP <mark style="color:purple;">GET</mark> operation is still considered safe because the client did not request the side effect.

### Idempotent <a href="#idempotent" id="idempotent"></a>

An idempotent method has an identical outcome if called multiple times. This means that after the initial HTTP request is sent, successive HTTP requests are of no consequence.

The idempotent HTTP methods are: <mark style="color:purple;">GET, HEAD, OPTIONS, TRACE, DELETE</mark>, and <mark style="color:purple;">PUT</mark>.&#x20;

All safe methods are idempotent, but <mark style="color:purple;">DELETE</mark> and <mark style="color:purple;">PUT</mark> are not safe because they intentionally affect the state of the server.

#### Cacheable <a href="#cacheable" id="cacheable"></a>

A cacheable method generates a HTTP response that can be cached.&#x20;

HTTP <mark style="color:purple;">GET</mark> and HEAD requests are cacheable.

### **HEAD** <a href="#id-5-head" id="id-5-head"></a>

* **Description**: Retrieves only headers (no response body). Useful for checking resource availability.
* **Characteristics**: Idempotent , Safe, Cacheable
* **Annotation**:  <mark style="color:purple;">`@RequestMapping(method = RequestMethod.HEAD)`</mark>
* **Status Code**:  <mark style="color:green;">200</mark> , <mark style="color:red;">404, 400</mark>

### **OPTIONS** <a href="#id-6-options" id="id-6-options"></a>

* **Description**: It is used to inquire about what operations are available for the specified resource or server in general.
* **Characteristics**: Idempotent , Safe
* **Annotation**:  <mark style="color:purple;">`@RequestMapping(method = RequestMethod.OPTIONS)`</mark>
* **Status Code**:  <mark style="color:green;">204</mark> ,  <mark style="color:red;">400, 500</mark>

### **TRACE** <a href="#id-9-trace" id="id-9-trace"></a>

* **Description**: Performs a diagnostic loop-back test to see how a request travels through intermediaries.
* **Characteristics**:  Idempotent , Safe
* **Annotation**:  <mark style="color:purple;">`@RequestMapping(method = RequestMethod.TRACE)`</mark>
* **Status Code**:  <mark style="color:green;">200</mark> ,  <mark style="color:red;">405</mark>

### **GET** <a href="#id-1-get" id="id-1-get"></a>

* **Description**: Used to retrieve data from a server. Does not modify the resource.
* **Characteristics**: Idempotent, Cacheable, Safe (can alter state)
* **Annotation**:  <mark style="color:purple;">`@GetMapping`</mark>
* **Status Code**:  <mark style="color:green;">200, 204</mark> ,  <mark style="color:red;">400, 404, 500</mark>

### **POST** <a href="#id-2-post" id="id-2-post"></a>

* **Description**: Sends data to the server, often to create a resource or trigger processing.
* **Characteristics**:&#x20;
  * **Idempotent**: No (repeated requests can create duplicate resources).
  * **Safe**: No (alters server state).
  * **Cacheable**: No (response is typically not cached).
* **Annotation**:  <mark style="color:purple;">`@PostMapping`</mark>
* **Status Code**:  <mark style="color:green;">201, 200, 207 \[multi]</mark> ,  <mark style="color:red;">400, 409, 500</mark>

### **PUT** <a href="#id-3-put" id="id-3-put"></a>

* **Description**: Replaces the entire target resource with the request payload.
* **Characteristics**:
  * **Idempotent**: Yes (subsequent requests with the same payload have the same effect).
  * **Safe**: No.
  * **Cacheable**: No.
* **Annotation**:  <mark style="color:purple;">`@PutMapping`</mark>
* **Status Code**:  <mark style="color:green;">201, 200, 204</mark> ,  <mark style="color:red;">400, 404, 500</mark>

### **PATCH** <a href="#id-7-patch" id="id-7-patch"></a>

* **Description**: Partially updates a resource, allowing modification of specific fields.
* **Characteristics**:
  * **Idempotent**: No (behavior depends on server implementation).
  * **Safe**: No.
  * **Cacheable**: No.
* **Annotation**:  <mark style="color:purple;">`@PatchMapping`</mark>
* **Status Code**:  <mark style="color:green;">200, 204</mark> ,  <mark style="color:red;">400, 404, 500</mark>

### **DELETE** <a href="#id-4-delete" id="id-4-delete"></a>

* **Description**: Deletes a resource identified by the URL.
* **Characteristics**: Idempotent
* **Annotation**:  <mark style="color:purple;">`@DeleteMapping`</mark>
* **Status Code**:  <mark style="color:green;">200, 204</mark> ,  <mark style="color:red;">400, 404, 500</mark>

### **CONNECT** <a href="#id-8-connect" id="id-8-connect"></a>

* **Description**: Establishes a network connection tunnel, often used for HTTPS requests.
* **Characteristics**: None

###

### Bulk Creation \[Post]

```java
 // Bulk creation with partial success handling
    @PostMapping("/batch")
    public ResponseEntity<BulkOperationResult<ProductDTO>> createProducts(
     @RequestBody List<ProductDTO> products) {
        BulkOperationResult<ProductDTO> result = productService.bulkCreate(products);
        
        if (result.hasPartialFailures()) {
            return ResponseEntity
                .status(HttpStatus.MULTI_STATUS)  // Returns 207 Multi-Status
                .body(result);
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(result);
    }
```

### Conditional Update \[Put]

```java
// Conditional update using ETag
    @PutMapping("/{customerId}")
    public ResponseEntity<CustomerDTO> updateCustomerConditional(
            @PathVariable String customerId,@RequestBody CustomerDTO customer,
            @RequestHeader("If-Match") String etag) {
        
        try {
            CustomerDTO updated = customerService.updateWithETag(customer, etag);
            return ResponseEntity.ok()
                .eTag("\"" + updated.getVersion() + "\"")
                .body(updated);
        } catch (OptimisticLockException e) {
            return ResponseEntity
                .status(HttpStatus.PRECONDITION_FAILED)  // Returns 412 Precondition Failed
                .build();
        }
    }
```

### Partial Update \[Patch]

```java
// Partial update using JSON Patch
    @PatchMapping(value = "/{orderId}", 
                 consumes = "application/json-patch+json")
    public ResponseEntity<OrderDTO> patchOrder(
            @PathVariable String orderId,
            @RequestBody JsonPatch patch) {
        
        try {
            OrderDTO patched = orderService.applyPatch(orderId, patch);
            return ResponseEntity.ok()  // Returns 200 OK
                .body(patched);
        } catch (JsonPatchException e) {
            return ResponseEntity
                .status(HttpStatus.UNPROCESSABLE_ENTITY)  // Returns 422 Unprocessable Entity
                .build();
        }
    }
    
    // Status update - specific business operation
    @PatchMapping("/{orderId}/status")
    public ResponseEntity<OrderDTO> updateOrderStatus(
            @PathVariable String orderId,
            @Valid @RequestBody OrderStatusUpdate statusUpdate) {
        
        try {
            OrderDTO updated = orderService.updateStatus(orderId, statusUpdate);
            return ResponseEntity.ok(updated);
        } catch (IllegalStateException e) {
            return ResponseEntity
                .status(HttpStatus.CONFLICT)  // Returns 409 Conflict
                .build();
        }
    }
```

### Bulk Delete \[Delete]

```java
 // Single resource deletion
    @DeleteMapping("/{productId}")
    public ResponseEntity<Void> deleteProduct(@PathVariable String productId) {
        productService.delete(productId);
        return ResponseEntity
            .noContent()  // Returns 204 No Content
            .build();
    }
    
    // Bulk deletion with preconditions
    @DeleteMapping
    public ResponseEntity<Void> deleteProducts(
            @RequestParam List<String> ids,
            @RequestHeader("If-Match") String etag) {
        
        try {
            productService.bulkDelete(ids, etag);
            return ResponseEntity
                .noContent()
                .build();
        } catch (OptimisticLockException e) {
            return ResponseEntity
                .status(HttpStatus.PRECONDITION_FAILED)
                .build();
        }
    }
```

### How to handle deletion of same resource multiple times ?

1. **For Pure REST APIs**:
   * Return 204 for all successful DELETE operations
   * This follows REST idempotency principles
   * Simplest to implement and use

```java
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
    // Even if resource doesn't exist, return 204
    // The end state is the same - resource doesn't exist
    productService.delete(id);
    return ResponseEntity.noContent().build();
}
```

2. **For Business-Critical Systems**:
   * Consider using 410 GONE for already deleted resources
   * Maintain deletion audit trail
   * More complex but provides better tracking

```java
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
    DeletionResult result = productService.delete(id);
    
    return switch (result) {
        case DELETED -> ResponseEntity.noContent().build();        // 204
        case ALREADY_DELETED -> ResponseEntity.status(410).build(); // 410 GONE
        case NOT_FOUND -> ResponseEntity.notFound().build();       // 404
    };
}
```

3. **For Event-Driven Systems**:
   * Use soft deletes
   * Publish deletion events
   * Maintain complete state history

```java
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable String id) {
    try {
        DeletionEvent event = productService.softDelete(id);
        eventPublisher.publish(event);
        
        return ResponseEntity.noContent().build();
    } catch (ResourceAlreadyDeletedException e) {
        // Still return 204 for idempotency
        return ResponseEntity.noContent().build();
    }
}
```

### Status Codes

Here’s a table listing HTTP status codes commonly used in API development.

<table data-header-hidden data-full-width="true"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><strong>Code</strong></td><td><strong>Name</strong></td><td><strong>Description</strong></td></tr><tr><td>100</td><td>Continue</td><td>The client should continue the request or ignore the response if the request is already finished.</td></tr><tr><td>101</td><td>Switching Protocols</td><td>The server is switching protocols as requested by the client.</td></tr><tr><td>102</td><td>Processing (WebDAV)</td><td>The server has received and is processing the request but no response is available yet.</td></tr><tr><td></td><td></td><td></td></tr><tr><td>200</td><td>OK</td><td>The request was successful, and the server returned the requested data.</td></tr><tr><td>201</td><td>Created</td><td>The request was successful, and a new resource was created.</td></tr><tr><td>202</td><td>Accepted</td><td>The request has been accepted for processing, but the processing is not complete.</td></tr><tr><td>204</td><td>No Content</td><td>The server successfully processed the request, but no content is returned.</td></tr><tr><td></td><td></td><td></td></tr><tr><td>301</td><td>Moved Permanently</td><td>The resource has been moved to a new URL permanently.</td></tr><tr><td>302</td><td>Found (Temporary Redirect)</td><td>The resource has temporarily moved to a different URL.</td></tr><tr><td>304</td><td>Not Modified</td><td>The requested resource has not been modified since the last access.</td></tr><tr><td></td><td></td><td></td></tr><tr><td>400</td><td>Bad Request</td><td>The server could not understand the request due to invalid syntax or parameters.</td></tr><tr><td>401</td><td>Unauthorized</td><td>Authentication is required to access the resource.</td></tr><tr><td>403</td><td>Forbidden</td><td>The client does not have permission to access the resource.</td></tr><tr><td>404</td><td>Not Found</td><td>The server could not find the requested resource.</td></tr><tr><td>405</td><td>Method Not Allowed</td><td>The HTTP method is not allowed for the requested resource.</td></tr><tr><td>409</td><td>Conflict</td><td>The request conflicts with the current state of the resource.</td></tr><tr><td>422</td><td>Unprocessable Entity</td><td>The server understands the content type but was unable to process the contained instructions.</td></tr><tr><td>429</td><td>Too Many Requests</td><td>The client has sent too many requests in a given time period.</td></tr><tr><td></td><td></td><td></td></tr><tr><td>500</td><td>Internal Server Error</td><td>The server encountered an unexpected condition that prevented it from fulfilling the request.</td></tr><tr><td>501</td><td>Not Implemented</td><td>The server does not support the functionality required to fulfill the request.</td></tr><tr><td>503</td><td>Service Unavailable</td><td>The server is not ready to handle the request, often due to maintenance or overloading.</td></tr><tr><td>504</td><td>Gateway Timeout</td><td>The server did not receive a timely response from an upstream server or external service.</td></tr><tr><td>511</td><td>Network Authentication Required</td><td>The client needs to authenticate to gain network access.</td></tr></tbody></table>

### Status Code Best Practices

Here's a summary of when to use specific status codes:

1. **Success Codes (2xx):**
   * 200 OK: Successful GET, PUT, PATCH
   * 201 Created: Successful POST creating new resource
   * 204 No Content: Successful DELETE
   * 207 Multi-Status: Batch operations with partial success
2. **Client Error Codes (4xx):**
   * 400 Bad Request: Invalid syntax
   * 401 Unauthorized: Authentication required
   * 403 Forbidden: Authenticated but not authorized
   * 404 Not Found: Resource doesn't exist
   * 409 Conflict: Business rule violation
   * 412 Precondition Failed: ETag mismatch
   * 422 Unprocessable Entity: Validation errors
3. **Server Error Codes (5xx):**
   * 500 Internal Server Error: Unexpected server errors
   * 503 Service Unavailable: Service temporarily unavailable
