0

I've read through a lot of questions regarding this error on Stack Overflow, but none of the solutions applied to me.

Context

My application runs without any errors when ran locally. However, when deploying my application to AWS Elastic Beanstalk, I get the following errors, seen when I run eb logs.

[Tue May 18 18:36:13.563576 2021] [:error] [pid 3428] [remote 127.0.0.1:0] mod_wsgi (pid=3428): Target WSGI script '/opt/python/current/app/app/routes.py' cannot be loaded as Python module.
[Tue May 18 18:36:13.563640 2021] [:error] [pid 3428] [remote 127.0.0.1:0] mod_wsgi (pid=3428): Exception occurred processing WSGI script '/opt/python/current/app/app/routes.py'.
[Tue May 18 18:36:13.564335 2021] [:error] [pid 3428] [remote 127.0.0.1:0] Traceback (most recent call last):
[Tue May 18 18:36:13.564370 2021] [:error] [pid 3428] [remote 127.0.0.1:0]   File "/opt/python/current/app/app/routes.py", line 16, in <module>
[Tue May 18 18:36:13.564376 2021] [:error] [pid 3428] [remote 127.0.0.1:0]     @application.route('/api/login', methods=['POST'], endpoint='login')
[Tue May 18 18:36:13.564383 2021] [:error] [pid 3428] [remote 127.0.0.1:0]   File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1315, in decorator
[Tue May 18 18:36:13.564387 2021] [:error] [pid 3428] [remote 127.0.0.1:0]     self.add_url_rule(rule, endpoint, f, **options)
[Tue May 18 18:36:13.564392 2021] [:error] [pid 3428] [remote 127.0.0.1:0]   File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 98, in wrapper_func
[Tue May 18 18:36:13.564396 2021] [:error] [pid 3428] [remote 127.0.0.1:0]     return f(self, *args, **kwargs)
[Tue May 18 18:36:13.564402 2021] [:error] [pid 3428] [remote 127.0.0.1:0]   File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1284, in add_url_rule
[Tue May 18 18:36:13.564415 2021] [:error] [pid 3428] [remote 127.0.0.1:0]     "existing endpoint function: %s" % endpoint
[Tue May 18 18:36:13.564432 2021] [:error] [pid 3428] [remote 127.0.0.1:0] AssertionError: View function mapping is overwriting an existing endpoint function: login

The following is my routes.py, which produces no errors when ran locally, but produces the errors when deployed to Elastic Beanstalk:

from flask import request, jsonify
from app.application import application
from app.extensions import db
from app.models import User, Subreddit, Keyword
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from sqlalchemy.exc import IntegrityError
import re
from functools import wraps

@application.route('/')

@application.route('/index')

@application.route('/api/login', methods=['POST'], endpoint='login')
def login():
    # Parse the incoming request
    incoming = request.get_json()
    email = incoming["email"]
    password = incoming["password"]

    # Check the database to see if the user exists. If successful, the route sends
    # a token back to the action, which stores the token into the redux state (reducer).
    user = User.query.filter_by(email=email).one()
    if user and user.check_password(password):
        # Generate a token for the user to send back to the frontend for authentication purposes.
        s = Serializer(application.config['SECRET_KEY'], expires_in=36000)
        token = s.dumps({
            'id': user.id,
            'email': user.email,
        }).decode('utf-8')

        # Return the user to the frontend in order to populate the loggedInUser redux state.
        return jsonify(token=token, user=user.serialize())
    elif user and not user.check_password(password):
        return jsonify(error=True), 401

    # If the user doesn't exist
    return jsonify(error=True), 404

//...

Problem

How can I resolve the error: AssertionError: View function mapping is overwriting an existing endpoint function: login?

What I've Tried

  • I've confirmed that there are no other decorated functions that share a name with login().
  • I've tried renaming the login() to a random name, such as login2() to confirm there is no naming conflict. The error message is still produced with a random name.
  • I've used the .route() argument endpoint to explicitly specify the view.
  • I've confirmed there are no identical function names in all my routes.
  • I've tried to make sure there are no circular imports. The following are the imports for each file:

My project's directory/structure:

> app/
>> __init__.py
>> application.py
>> extensions.py
>> models.py
>> routes.py
> migrations/
> venv/
> .flaskenv
> app.db
> config.py
> requirements.txt
> script.py

My __init__.py:

from app import routes

My application.py:

from flask import Flask
from config import Config


application = Flask(__name__)

application.config.from_object(Config)

My extensions.py:

from app.application import application
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from apscheduler.schedulers.background import BackgroundScheduler

db = SQLAlchemy(application)

migrate = Migrate(application, db, render_as_batch=True)

scheduler = BackgroundScheduler(daemon=True) 

My routes.py:

from app.application import application
from app.extensions import db
from app.models import User, Subreddit, Keyword

My models.py:

from app.extensions import db

For the full project: https://github.com/boxcarcoder/Reddalerts

  • I've also tried removing the scheduler in extensions.py in case it was causing multiple instantiations of my api routes (although that is unlikely, but I am running low on potential ideas for the cause of this issue).

Potential Solution?

I see solutions mentioning using wraps, but how I can I wrap the route() decorator? What is the purpose of using wraps? When I run my application locally and outside of Elastic Beanstalk, there are no issues with my code as the way it is.

Brendan
  • 752
  • 1
  • 8
  • 21
  • As far as I can tell the endpoint parameter is superfluous here. What happens if you just remove it ? – Kate May 18 '21 at 20:47
  • No change after I remove the endpoint parameter. I also thought it may be superfluous but have seen a solution on Stack Overflow stating it may help. However, that did not apply in my situation. – Brendan May 18 '21 at 22:30
  • Is this the whole code ? Have you had a look at the included files, and perhaps other files present in your directory structure ? Seeing that your path contains app/app, I wouldn't be surprised that you are unwittingly importing other files lingering around as modules perhaps. – Kate May 19 '21 at 21:04
  • I have updated my the post to show my included files. I believe I do not have repeat of function names. – Brendan May 19 '21 at 21:41

1 Answers1

0

The problem was in how Elastic Beanstalk configures its environment. I was only considering my application's code, when I should have considered the entire code base. The following is my directory structure, including the directories required by Elastic Beanstalk.

> app/
>> .ebextensions/
>>> reddalerts.config
>> .elasticbeanstalk/
>>> config.yml
>> __init__.py
>> application.py
>> extensions.py
>> models.py
>> routes.py
> migrations/
> venv/
> .flaskenv
> app.db
> config.py
> requirements.txt
> script.py

In the .ebextensions directory, I have a config file, reddalerts.config to designate the WSGIPath for Elastic Beanstalk:

option_settings:
  "aws:elasticbeanstalk:container:python":
    WSGIPath: app/routes.py

Following this question/solution: How to deploy structured Flask app on AWS elastic beanstalk, I thought the WSGIPath should point to my views file (app/routes.py), but that was incorrect for my situation. It should point to the application module (application.py).

After changing my reddalerts.config to the following, the issue resolved.

option_settings:
  "aws:elasticbeanstalk:container:python":
    WSGIPath: application.py
Brendan
  • 752
  • 1
  • 8
  • 21