0

I'm trying to get my API to work on my Ubuntu VPS using Apache, this is my FLASK code;

#!/usr/bin/env python
import os
from sqlalchemy import update
from flask import Flask, abort, request, jsonify, g, url_for
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.httpauth import HTTPBasicAuth
from passlib.apps import custom_app_context as pwd_context
from itsdangerous import (TimedJSONWebSignatureSerializer
                          as Serializer, BadSignature, SignatureExpired)
from datetime import datetime
import math


# initialization
app = Flask(__name__)
app.config['SECRET_KEY'] = 'the quick brown fox jumps over the lazy dog'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True

# extensions
db = SQLAlchemy(app)
auth = HTTPBasicAuth()


class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    username = db.Column(db.String(32), index=True)
    password_hash = db.Column(db.String(64))

    def hash_password(self, password):
        self.password_hash = pwd_context.encrypt(password)

    def verify_password(self, password):
        return pwd_context.verify(password, self.password_hash)

    def generate_auth_token(self, expiration=600):
        s = Serializer(app.config['SECRET_KEY'], expires_in=expiration)
        return s.dumps({'id': self.id})

    @staticmethod
    def verify_auth_token(token):
        s = Serializer(app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except SignatureExpired:
            return None    # valid token, but expired
        except BadSignature:
            return None    # invalid token
        user = User.query.get(data['id'])
        return user


class Points(db.Model):
    __tablename__ = 'points'
    id = db.Column(db.Integer, primary_key=True)
    date = db.Column(db.String(32))
    username = db.Column(db.String(32))
    shop = db.Column(db.String(64))
    point = db.Column(db.Integer)


class MyPoints(db.Model):
    __tablename__ = 'mypoints'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(32))
    shop = db.Column(db.String(64))
    point = db.Column(db.Integer)

class Shops(db.Model):
    __tablename__ = 'shop'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    location = db.Column(db.String(32))
    website = db.Column(db.String(32))
    number = db.Column(db.String(32))
    message = db.Column(db.String(32))

@auth.verify_password
def verify_password(username_or_token, password):
    # first try to authenticate by token
    user = User.verify_auth_token(username_or_token)
    if not user:
        # try to authenticate with username/password
        user = User.query.filter_by(username=username_or_token).first()
        if not user or not user.verify_password(password):
            return False
    g.user = user
    return True


@app.route('/api/users/reg', methods=['POST'])
def new_user():
    name = request.json.get('name')
    username = request.json.get('username')
    password = request.json.get('password')
    if username is None or password is None or name is None:
        return (jsonify({'status': "Missing fields"}))
        abort(400)    # missing arguments
    if User.query.filter_by(username=username).first() is not None:
        return (jsonify({'status': "Email already Exists"}))
        abort(400)    # existing user
    user = User(username=username, name=name)
    user.hash_password(password)
    db.session.add(user)
    db.session.commit()
    return (jsonify({'status': "Account Created"}), 201)

@app.route('/api/users/up', methods=['POST'])
def update_password():
    username = request.json.get("username")
    password = request.json.get('password')
    if password is None or username is None:
        return (jsonify({'status': "Missing fields"}))
        abort(400)    # missing arguments
    user = pwd_context.encrypt(password)
    result = db.engine.execute('UPDATE users SET password_hash = "%s" WHERE username = "%s"' % (user, username))

    return (jsonify({'status': "Password Updated"}), 201)

@app.route('/api/users/log', methods=['GET'])
@auth.login_required
def login_user():
    token = g.user.generate_auth_token(600)
    return jsonify({'status': 'Logged in'})

@app.route('/api/users/del', methods=['POST'])
@auth.login_required
def delete_account():
    username = g.user.username
    if username is None:
        return (jsonify({'status': "Missing fields"}))
        abort(400)    # missing arguments

    db.engine.execute("DELETE FROM users WHERE username = '%s'" % username)

    return (jsonify({'status': "Account Deleted"}), 201)




@app.route('/api/points/list', methods=['GET'])
@auth.login_required
def all_points():
    user = g.user.username
    result = MyPoints.query.filter_by(username=user).limit(10).offset(0)

    json_results = []
    for result in result:
      d = {'id': result.id,
           'shop': result.shop,
           'point': result.point,
           'username': result.username}
      json_results.append(d)

    return jsonify(items=json_results)

@app.route('/api/points/<path:shop>', methods=['GET'])
@auth.login_required
def list_points(shop):
    user = g.user.username
    result = MyPoints.query.filter_by(shop=shop).limit(10).offset(0)

    json_results = []
    for result in result:
      d = {'id': result.id,
           'shop': result.shop,
           'point': result.point,
           'username': result.username}
      json_results.append(d)

    return jsonify(items=json_results, )



@app.route('/api/points', methods=['POST'])
@auth.login_required
def update_points():
    date = str(datetime.now())
    username = request.json.get('username')
    shop = request.json.get('shop')
    point = request.json.get('point')
    user = Points(date=date, username=username, shop=shop, point=point)
    db.session.add(user)
    db.session.commit()
    result = db.engine.execute('select point from points WHERE shop == "%s" AND username="%s"' % (shop, username))
    names = []
    for row in result:
        names.append(row[0])
    names = [x.encode('utf-8') for x in names]
    results = map(int, names)
    r = sum(results)
    result = db.engine.execute('UPDATE mypoints SET point = "%s" WHERE username = "%s"' % (r, username))
    return (jsonify({'Points': r}), 201)



if __name__ == '__main__':
    if not os.path.exists('db.sqlite'):
        db.create_all()
    app.run(debug=True)

Every time I try run a Curl Command;

curl -i -X POST -H "Content-Type: application/json" -d '{"username":"miguel","password":"python"}' http://adventorious.com/api/users

It throws;

HTTP/1.1 500 Internal Server Error
Date: Sun, 15 Feb 2015 16:01:37 GMT
Server: Apache/2.4.7 (Ubuntu)
Content-Length: 623
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator at 
 administrator@91.103.6.23 to inform them of the time this error occurred,
 and the actions you performed just before this error.</p>
<p>More information about this error may be available
in the server error log.</p>
<hr>
<address>Apache/2.4.7 (Ubuntu) Server at adventorious.com Port 80</address>
</body></html>

I don't understand why this is happening as it runs perfectly on my computer locally but if I try run it from the VPS it just throws an error 500.

I've searched all over the web but I can't seem to find a solution.

All help is greatly appreciated.

ADDITION;

Here is the error;

[Sun Feb 15 16:17:53.470691 2015] [:error] [pid 1469] [client 178.167.254.175:4226] mod_wsgi (pid=1469): Target WSGI script '/var/www/FlaskApi/api.wsgi' cannot be loaded as Python module.
[Sun Feb 15 16:17:53.470790 2015] [:error] [pid 1469] [client 178.167.254.175:4226] mod_wsgi (pid=1469): Exception occurred processing WSGI script '/var/www/FlaskApi/api.wsgi'.
[Sun Feb 15 16:17:53.470817 2015] [:error] [pid 1469] [client 178.167.254.175:4226] Traceback (most recent call last):
[Sun Feb 15 16:17:53.470849 2015] [:error] [pid 1469] [client 178.167.254.175:4226]   File "/var/www/FlaskApi/api.wsgi", line 6, in <module>
[Sun Feb 15 16:17:53.470932 2015] [:error] [pid 1469] [client 178.167.254.175:4226]     from FlaskApi import app as application
[Sun Feb 15 16:17:53.470957 2015] [:error] [pid 1469] [client 178.167.254.175:4226] ImportError: No module named FlaskApi

I say; from FlaskApi import app

but the wsgi and the init file are in the same place, is this the problem>>?

Sean Downey
  • 25
  • 1
  • 5
  • If you look at the server logs, you shall see some detailed information about what is happening (typically an exception trace). If you post it, it will be easier to understand what is happening – Jeff Feb 15 '15 at 16:11
  • Could you also post some info regarding your Apache setup? You're curl'ing to localhost:5000, so is Apache listening on port 5000 and then re-directing to... a Flask dev server running on a different port? – SJoshi Feb 15 '15 at 16:13
  • Sorry, had it on wrong port in the example above. @SJoshi – Sean Downey Feb 15 '15 at 16:27
  • @SeanDowney Ohh, I hate these problems. Could it be your python path isn't correctly set up? In the past, I've tested this by adding a simple: import sys sys.path.append('../') # Hack to not have to deal with PythonPath – SJoshi Feb 16 '15 at 03:05
  • @SeanDowney Also, are you using virtualenvs? Maybe you're not enabling one? Typically, that kind of error for me is indicative of uwsgi is not using my pythonpath, or virtualenv, or similar. – SJoshi Feb 16 '15 at 03:06

1 Answers1

1

It looks like you are indeed trying to import app from FlaskApi, but you are already in it.

Can you try to change the line 6 of your script to:

from . import app as application

or

import app as application

to test things faster (and avoid restarting the server all the time), you can also just try to run:

python /var/www/FlaskApi/api.wsgi
fsiddi
  • 101
  • 6