How to run a Python API Web Service with cPanel

The Python Virtual Environment

Libraries is a compilation of code wrote by other people, organization or even a complete community of programmers. These libraries help you avid re-writing large pieces of code for common tasks like transforming data from one type to another, or setting up a server. Since libraries can be…..

Python can use virtual environments to avoid version mismatch between projects. Maybe one application was wrote using a specific version of a library, or maybe you have a exclusive library that conflicts with other libraries… that is why you want virtual envirorments; they help you isolate your application like if it was alone in your system. That also means that you have a clean slate and may have to install all libraries individually,

source <path of the virtual envirorment>

source virtualenv/python_api/3.8/bin/activate

Summary

source virtualenv/python_api/3.8/bin/activate
pip install subprocess
pip install flask
from urllib import parse

def application(req,res):
    request = parse(req);
    #scheme, netloc, path, params, query, fragment
    return encode("Path: "+request.path + "\nQuery: " + request.query + "\nParams" + request.params);
import subprocess
  
# If your shell script has shebang (#!/bin/bash), 
# you can omit shell=True argument.
subprocess.run(["/path/to/your/shell/script", 
                "arguments"], shell=True)

This is a great tutorial to setup a bare-bones Flask Applicationon cPanel: How to Host Flask Application on CPanel? But the summary of the code is this:

from flask import Flask

app = Flask(__name__)

# this is the entry point
application = app

@app.route("/")
def hello():
    return "Congratulation! You service Hosted on CPanel"

if __name__ == "__main__":
    app.run()

Flask: all you need to know

There are many blog posts entirely dedicated to using flask, maybe I’ll post some in the future. But for now I want to keep it simple.

app = Flask(name)

This is the base of the project. We are defining an object “app” which is going to help us build the entire server. All you need to know is that this line comes before anything you want to do with server functions.

Defining Endpoints

This is the way of defining a new endpoint. You can create as many as you want. By default they will answer only GET requests (or requests from browsers):

@app.route("/endpoint_1")
def endpoint():
    data = request.json # Receive any data sent
    
    # Place your code for this endpoint here
    
    return "Success!", 200    #Respond with a message and status code

I want to focus your attention on 3 places:

  1. Definition of the endpoint (line 1)
  2. Parsing incoming data (line 3)
  3. Returning a message (last line)
Definition of the endpoint (part 1)

You can define the endpoint with the following structure:

@app.route("/path/of/your/endpoint")  # you can get here through
                                      # https://example.com/api/path/of/your/endpoint
def any_name_you_want():
   return 200; #always return something

The name of the function has no effect what so ever. BestPractice-Tip: Name it the same as your endpoint. This way you’ll avoid duplicate functions and will improve the overall readability of your code.

Definition of the endpoint (part 2)

You can define the endpoint with the following structure:

@app.route("/users",methods=['POST']) # Limit the endpoint to only POST requests
def users():
   return 200; #always return something

The name of the function has no effect what so ever. BestPractice-Tip: Name it the same as your endpoint. This way you’ll avoid duplicate functions and will improve the overall readability of your code.

@app.route("/users",methods=['GET']) # Limit the endpoint to only GET requests
def users_get():
   return 200; #always return something

@app.route("/users",methods=['POST']) # Limit the endpoint to only POST requests
def users_post():
   return 200; #always return something
Definition of the endpoint (part 3)

We can make it better and more fancy if you have multiple routines for the same endpoint

@app.route("/users")
def users():
   def get():
       the_user = request.json;
       return "Here is the user: "+ the_user, 200;

   def post():
       save_new_user(request.json);
       return "Stored new user", 200;

The name of the function has no effect what so ever. BestPractice-Tip: Name it the same as your endpoint. This way you’ll avoid duplicate functions and will improve the overall readability of your code.

Parsing incoming data

We are going to use an integrated function of flask here

from flask import request # Import first

data = request.json # request will manage any data being sent.
                    # request.json will manage the data being sent as json. This is

Now we have a dictionary (sort of an object) “data” that has all data being sent by the user whether it is sent as a parameter on the url itself, as a header or as the body. We can easily read and manipulate the data now

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top