Wednesday, 11 September, 2019 UTC


Summary

Introduction

In this tutorial you will learn how to deploy a Flask application to Heroku. The app can be as simple as a "Hello World" app to a social media monitoring platform!
Nowadays there is no business that doesn't have a web app to help it a reach greater audience, or maybe provide its services through an online portal.
Today you are about to learn how to make an API using Flask as a case study for how to deploy your app on Heroku.

Building a REST API with Flask

In your project directory, let's start off by creating a virtualenv:
$ python -m venv venv/
And let's activate it with the source command:
$ source venv/bin/activate
Then, let's use pip to install the libraries we're going to use - flask to build the app and gunicorn as our server:
$ pip install flask
$ pip install gunicorn
Our application is going to be a simple API that receives a name and returns a welcome message:
# app.py
from flask import Flask, request, jsonify
app = Flask(__name__)

@app.route('/getmsg/', methods=['GET'])
def respond():
    # Retrieve the name from url parameter
    name = request.args.get("name", None)

    # For debugging
    print(f"got name {name}")

    response = {}

    # Check if user sent a name at all
    if not name:
        response["ERROR"] = "no name found, please send a name."
    # Check if the user entered a number not a name
    elif str(name).isdigit():
        response["ERROR"] = "name can't be numeric."
    # Now the user entered a valid name
    else:
        response["MESSAGE"] = f"Welcome {name} to our awesome platform!!"

    # Return the response in json format
    return jsonify(response)

@app.route('/post/', methods=['POST'])
def post_something():
    param = request.form.get('name')
    print(param)
    # You can add the test cases you made in the previous function, but in our case here you are just testing the POST functionality
    if param:
        return jsonify({
            "Message": f"Welcome {name} to our awesome platform!!",
            # Add this option to distinct the POST request
            "METHOD" : "POST"
        })
    else:
        return jsonify({
            "ERROR": "no name found, please send a name."
        })

# A welcome message to test our server
@app.route('/')
def index():
    return "<h1>Welcome to our server !!</h1>"

if __name__ == '__main__':
    # Threaded option to enable multiple instances for multiple user access support
    app.run(threaded=True, port=5000)
To test your application locally, let's hit the http://127.0.0.1:5000/ endpoint. If everything is fine, we should be greeted with a welcome message:
We can also send a name as a parameter, such as http://localhost:5000/getmsg/?name=Mark:
{"MESSAGE":"Welcome Mark to our awesome platform!!"}
With our application ready, let's deploy it to Heroku.

Heroku

Heroku is one of the first cloud platform as a service (PaaS) and supports several languages - Ruby, Java, Node.js, Scala, Clojure, Python, PHP, and Go.
The first thing we need to do is define which libraries our application uses. That way, Heroku knows which ones to provide for us, similar to how we install them locally when developing the app.
To achieve this, we need to create a requirements.txt file with all of the modules:
$ pip freeze > requirements.txt
This way we end up with a requirements.txt file that contains the libraries we're using and their versions:
Click==7.0
Flask==1.1.1
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
Werkzeug==0.15.6
Note: One of the common mistakes is misspelling requirements, it is a real pain when you debug your code for hours and find out that the app doesn't run because the server didn't download the modules. The only way for Heroku to know the modules that you are using is to add them to the requirements.txt file, so be careful!
For Heroku to be able to run our application like it should, we need to define a set of processes/commands that it should run beforehand. These commands are located in the file Procfile.txt:
web: gunicorn app:app
The web command tells Heroku to start a web server for the application, using gunicorn. Since our application is called app.py, we've set the app name to be app as well.

Heroku Account

Now, we should create a Heroku account.
Once that is out of the way, on the dashboard, select New -> Create new app:
Choose a name for the application and choose a region of where you'd like to host it:
Once the application is created on Heroku, we're ready to deploy it online.

Git

To upload our code, we'll use Git. First, let's make a git repository:
$ git init .
And now, let's add our files and commit:
$ git add app.py Procfile requirements.txt
$ git commit -m "first commit"

Deploying the App to Heroku

To finally deploy the application, we'll need to install the Heroku CLI with which we'll run Heroku-related commands. Let's login to our account using our credentials by running the command:
$ heroku login -i
Alternatively, we can login using the browser if we run the command:
$ heroku login
At this point, while logged in, we should add our repository to the remote one:
$ heroku git:remote -a {your-project-name}
Be sure to replace {your-project-name} with the actual name of your project you selected in the earlier step.
And with that done, let's upload the project by pushing it to Heroku:
$ git push heroku master
A lengthy progress log should come up on your terminal, ending with:
...
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 45.1M
remote: -----> Launching...
remote:        Released v4
remote:        https://{your-project-name}.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/{your-project-name}.git
   ae85864..4e63b46  master -> master
Congratulations, you have successfully uploaded your first web app to Heroku! It's now time now to test and verify our API.

Testing the API

In the log that has been shown in the console you will find a link for your application https://{your-project-name}.herokuapp.com/, this link can also be found under the Settings tab, in the Domains and certificates section:
Visiting the link, we can reach our application, which is now online and public:
In case there were any errors, you can access the logs and troubleshoot from there:
You can manually test your app in the browser, by typing the URL and adding the path for the /getmsg/ route. Though, as applications tend to get more and more complex, it's advised to use tools like Postman.
Now let's test the GET request to our application with a name parameter:
Now let's test a URL that isn't bound to any function, like for example /newurl, with a GET request:
As expected, our Flask app returned a 404 response.
Note: You can change the view of the output from Pretty, Raw, and Preview, which shows you how the output would look in your browser.
Now let's test a POST request:
Also, let's see what happens if we completely omit the name parameter:
{"ERROR":"no name found, please send a name."}
We've tested our app and confirmed that everything is working fine. To see the history of your server and what requests were made you can check the logs for your site via Heroku:
You can see here the POST request we made to our page /post/.
Also, you can see the history of building the application. Moreover, if there's any problem during building you can find it in the log page.

Conclusion

In this article we showed a simple example of building our first simple API on Heroku using the Flask micro-framework. The development process remains the same as you continue to build your application.
Heroku offers a free plan and Student plans. The free plan is limited but it works pretty good for a starting app, POC, or a simple project for example. However, if you want to scale your application then you'll want to consider one of the plans that are available on the site from here.
For more info on Heroku you can check the Heroku manual itself.