Search code examples
pythonflaskapi-designendpointflask-restful

Why does Flask-RESTful' add_resource() has a parameter for URLs and another one for endpoints?


I'm developing an API using Flask and the Flask-RESTful extension. I'm creating my endpoints and resources, but I'm confused with the difference between the resource "url" and its "endpoint". To my understanding, the URL itself is the endpoint. I was also reading the answers to this StackOverflow question and they also suggest that an URL is an endpoint.

Yet the Flask-RESTful docs mentions that the add_resource method has an argument for URLs and it can also receive an endpoint name. They even provide this example:

api.add_resource(HelloWorld, '/', '/hello')
api.add_resource(Foo, '/foo', endpoint="foo")
api.add_resource(FooSpecial, '/special/foo', endpoint="foo")

In which I understand what they are doing, but again I don't understand what the endpoint name does.

What is the difference between the URL and the endpoint name? And why would I set an endpoint name?


Solution

  • From the documentation:

    URL

    one or more url routes to match for the resource, standard flask routing rules apply. Any url variables will be passed to the resource method as args.

    ENDPOINT

    endpoint name (defaults to Resource.name.lower() Can be used to reference this route in fields.Url fields

    The endpoint parameter must be specified when you intend to manage two or more urls with the same class, in fact, considering the following code snippet:

    from flask import Flask, request
    from flask_restful import Api, Resource
        
        
    class my_handler(Resource):
        def get(self):
            return request.base_url
            
    app = Flask(__name__)
    api = Api(app)
            
    api.add_resource(my_handler, '/')
    api.add_resource(my_handler, '/hello')
            
    if __name__ == '__main__':
        app.run(host="0.0.0.0", port=5000)
    
    

    flask will not be able to execute the application, raising the exception:

    Exception has occurred: AssertionError       
    View function mapping is overwriting an existing endpoint function: my_handler
    

    In order for flask to handle multiple urls with the same class, you will need to specify the endpoint parameter:

    from flask import Flask, request
    from flask_restful import Api, Resource
    
    
    class my_handler(Resource):
        def get(self):
            return request.base_url
    
    app = Flask(__name__)
    api = Api(app)
    
    api.add_resource(my_handler, '/', endpoint='/')
    api.add_resource(my_handler, '/hello', endpoint='/hello')
    
    if __name__ == '__main__':
        app.run(host="0.0.0.0", port=5000)
    

    By making an http call, the server responds by returning the url of the requested resource:

    curl --location --request GET http://127.0.0.1:5000/
    "http://127.0.0.1:5000/"
    
    curl --location --request GET http://127.0.0.1:5000/hello
    "http://127.0.0.1:5000/hello"