Search code examples
pythonhtmlflaskweb-applicationsflask-restful

flask application error for PUT method: "The method is not allowed for the requested URL."


I'm building a REST API application using Python flask. I'm getting >405 Method Not Allowed< error while sending request as PUT and DELETE methods. Getting proper results while using GET and POST. I'm circling without solutions. Most of the solutions already provided has either because of the method missing in HTML template or function argument.But in my case I'm using API calls to the endpoints using curl.

from flask import Flask, jsonify, request

products = [
    {'id': 0, 'name': 'Product 0'},
    {'id': 1, 'name': 'Product 1'}
]

app = Flask(__name__)


# curl -v http://localhost:8080/products
@app.route('/products')
def index():
    return jsonify(products)


# curl -v http://localhost:8080/product/0
@app.route('/product/<int:id>')
def get_product_id(id):
    product_list = [product for product in products if product['id'] == id]
    if not product_list:
        return f'Product with id {id} not found!', 404
    return jsonify(product_list[0])


# curl
# --header "Content-Type: application/json"
# --request POST
# --data '{"name": "Product 3"}' -v http://localhost:8080/product/
@app.route('/product', methods=['POST'])
def add_product():
    # Retrieve the product from request body
    data = request.json

    # Generate an ID for the post
    new_id = max([product['id'] for product in products]) + 1

    # Create new product
    new_product = {
        'id': new_id,
        'name': data['name']
    }
    # add new product to the array
    products.append(new_product)

    return jsonify(new_product)


# curl --header "Content-Type: application/json"
# --request PUT
# --data '{"name": "Updated Product 2"}'
# -v http://localhost:8080/product/<int:id>

@app.route('/product/<int>:id', methods=['PUT'])
def update_product(id):
    change_data = request.json

    # Find product if available
    for product in products:
        if product['id'] == id:
            product['name'] = change_data['name']
            return jsonify(product), 200
    return f'Product with id {id} not found', 404

# curl --request DELETE -v http://localhost:8080/product/2
@app.route('/product/<int>:id', methods=['DELETE'])
def delete_product(id):
    for product in products:
        if product['id'] == id:
            products.remove(product)
            return f'Product with id {id} removed', 200
    return f'Product with id {id} not found', 404


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

ERROR:

$ curl -v http://localhost:8080/products

* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /products HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 146
< Server: Werkzeug/2.0.1 Python/3.9.5
< Date: Fri, 13 Aug 2021 17:14:05 GMT
< 
[
  {
    "id": 0, 
    "name": "Product 0"
  }, 
  {
    "id": 1, 
    "name": "Product 1"
  }, 
  {
    "id": 2, 
    "name": "Product 2"
  }
]
* Closing connection 0


$ curl --header "Content-Type: application/json" --request PUT --data '{"name": "Updated Product 2"}' -v http://localhost:8080/product/2

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>
* Closing connection 0


Solution

  • You have a typo in your code. Change <int>:id to <int:id>.