Skip to content

HTTP Methods Reference — GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about HTTP Methods Reference. We cover key concepts, practical examples, and best practices to help you master this topic.

HTTP methods define the action to perform on a resource. GET retrieves, POST creates, PUT replaces, PATCH partially updates, DELETE removes, HEAD checks headers, and OPTIONS discovers available methods.

What You'll Learn

  • The semantics of each HTTP method
  • Which methods are safe, idempotent, and cacheable
  • Typical response codes for each method

Why It Matters

Choosing the wrong HTTP method creates confusion and breaks client expectations. A POST that's treated as idempotent, a DELETE that returns a body, or a PUT that partially updates all violate HTTP semantics and cause integration problems.

Real-World Use

DodaTech's API strictly follows HTTP method semantics: GET requests are safe and cacheable, PUT replaces entire resources, PATCH applies partial updates with JSON Patch, and DELETE returns 204 with no body. This predictability allows automated client generation and CDN Caching.

flowchart TD
    GET -->|"Safe, Idempotent, Cacheable"| R["Retrieve Resource"]
    HEAD -->|"Safe, Idempotent"| H["Headers Only"]
    POST -->|"Not Idempotent"| C["Create Resource"]
    PUT -->|"Idempotent"| U["Replace Resource"]
    PATCH -->|"Not Idempotent"| P["Partial Update"]
    DELETE -->|"Idempotent"| D["Remove Resource"]
    OPTIONS -->|"Safe"| O["Discover Methods"]
    style GET fill:#bbf7d0,stroke:#16a34a
    style POST fill:#fef3c7,stroke:#d97706
    style DELETE fill:#fecaca,stroke:#dc2626

GET Implementation

@app.route('/api/products/<int:product_id>', methods=['GET'])
def get_product(product_id):
    product = database.get_product(product_id)
    if not product:
        return jsonify({"error": "not_found", "message": "Product not found"}), 404

    response = jsonify(product.to_dict())
    response.headers['Cache-Control'] = 'public, max-age=60'
    response.headers['ETag'] = compute_etag(product)
    return response

POST Implementation

@app.route('/api/products', methods=['POST'])
def create_product():
    data = request.get_json()
    if not data or 'name' not in data:
        return jsonify({"error": "validation_error", "message": "Name is required"}), 400

    product = database.create_product(data)
    response = jsonify(product.to_dict())
    response.status_code = 201
    response.headers['Location'] = f"/api/products/{product.id}"
    return response

PUT vs PATCH

# PUT: full replacement (idempotent)
@app.route('/api/products/<int:product_id>', methods=['PUT'])
def replace_product(product_id):
    data = request.get_json()
    existing = database.get_product(product_id)
    if not existing:
        return jsonify({"error": "not_found"}), 404

    # Full replacement - missing fields are set to defaults
    product = database.update_product(product_id, data)
    return jsonify(product.to_dict())

# PATCH: partial update
@app.route('/api/products/<int:product_id>', methods=['PATCH'])
def update_product(product_id):
    data = request.get_json()
    if not data:
        return jsonify({"error": "no_data"}), 400

    # Only update provided fields
    product = database.partial_update(product_id, data)
    return jsonify(product.to_dict())

DELETE and HEAD

# DELETE: remove resource (returns 204 No Content)
@app.route('/api/products/<int:product_id>', methods=['DELETE'])
def delete_product(product_id):
    existing = database.get_product(product_id)
    if not existing:
        return jsonify({"error": "not_found"}), 404

    database.delete_product(product_id)
    return '', 204

# HEAD: returns headers only (same as GET but no body)
@app.route('/api/products/<int:product_id>', methods=['HEAD'])
def head_product(product_id):
    product = database.get_product(product_id)
    if not product:
        return '', 404

    response = make_response()
    response.headers['Content-Type'] = 'application/json'
    response.headers['Content-Length'] = estimate_content_length(product)
    response.headers['ETag'] = compute_etag(product)
    return response

# OPTIONS: discover available methods
@app.route('/api/products/<int:product_id>', methods=['OPTIONS'])
def options_product(product_id):
    response = make_response()
    response.headers['Allow'] = 'GET, PUT, PATCH, DELETE, HEAD, OPTIONS'
    return response

Common Mistakes

1. Using POST for Everything

Some developers use POST for all operations. This breaks cacheability and idempotency. Use GET for retrieval, PUT for replacement, DELETE for removal.

2. Returning a Body with DELETE

DELETE should return 204 No Content. Returning a body with the deleted resource is non-standard.

3. Partial Updates with PUT

PUT replaces the entire resource. A client expecting PUT to partially update will be surprised when omitted fields reset to defaults.

4. Not Returning Location Header on POST

POST should return a Location header pointing to the created resource. Forgetting this forces clients to guess the new resource URI.

5. Using POST for Safe Operations

POST is not safe or idempotent. Do not use POST for simple retrievals. Use GET.

Practice Questions

  1. Which HTTP methods are safe (don't change state)?
  2. Which methods are idempotent?
  3. What status code should a successful GET return?
  4. What should a successful DELETE return?
  5. What header should a successful POST include?

Answers

  1. GET, HEAD, OPTIONS are safe. 2. GET, HEAD, PUT, DELETE are idempotent. 3. 200 OK. 4. 204 No Content. 5. Location header pointing to the created resource.

Challenge

Build an API router that validates HTTP method usage: GET endpoints must be safe (no side effects), POST must return 201 with Location header, PUT must replace the entire resource, PATCH must only update provided fields, and DELETE must return 204.

FAQ

Why is GET safe?

GET is defined as a retrieval operation that should not change server state.

What does idempotent mean?

Making the same request multiple times has the same effect as making it once.

Why should DELETE return 204?

After deletion, there is no representation to return. 204 No Content signals successful deletion with no body.

What is the difference between PUT and PATCH?

PUT replaces the entire resource; PATCH applies only the provided changes.

What is the OPTIONS method used for?

To discover which HTTP methods are available for a resource.

Mini Project

Build an HTTP methods Compliance checker: a Flask API with all standard method implementations, a test suite that verifies each method's semantics (safety, idempotency, response codes, headers), and a CLI tool that tests any API for HTTP method compliance.

What's Next

  • Learn about GET design guidelines for safe and cacheable retrieval
  • Explore POST design for resource creation
  • Continue to PUT vs PATCH with JSON Patch and Merge Patch

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro