skip to Main Content

I’ve developed an api using fastapi that will act as a wrapper that receives sms requests and call the sms api to send said sms and now I’m ready to deploy it. This is the code:

import logging

import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fastapi.middleware.trustedhost import TrustedHostMiddleware

import verifier

logging.basicConfig(
    format='%(asctime)s - %(funcName)s - %(levelname)s - %(message)s',
    level=logging.INFO
)

# get logger
logger = logging.getLogger(__name__)


bot_verifier = None


class DataForBot(BaseModel):
    number: str
    msg_txt: str


def get_application():
    app = FastAPI(title='bot_wrapper', version="1.0.0")

    return app


app = get_application()


@app.on_event("startup")
async def startup_event():
    global bot_verifier
    try:
        bot_verifier = await verifier.Verifier.create()
    except Exception as e:
        logger.error(f"exception occured during bot creation -- {e}", exc_info=True)


@app.post('/telegram_sender/')
async def send_telegram_msg(data_for_bot: DataForBot):
    global bot_verifier
    if not bot_verifier:
        bot_verifier = await verifier.Verifier.create()
    else:
        dict_data = data_for_bot.dict()
        try:
            if await bot_verifier.send_via_telegram(dict_data):
                return {'status': "success", 'data': data_for_bot}
            else:
                raise HTTPException(status_code=404, detail="unable to send via telegram, perhaps user has not started the bot")
        except Exception as e:
            logger.error(f"{e}", exc_info=True)
            raise HTTPException(status_code=500, detail="Something went wrong, please contact server admin")

I want to deploy it on apache b/c it’s the only thing I can get my hand onto in my country. I’m using python3.8.9 with fastapi version 0.65.2 and apache/2.4.29, but for the life of me I can’t get it to work. I’ve written an apache conf file and enabled that as such:

<VirtualHost *:80>
    ServerName gargarsa.sms.local
    ServerAdmin webmaster@localhost
    ServerAlias gargarsa.sms.local
    
    DocumentRoot /var/www/verify_bot_api/
    ServerAlias gargarsa.sms.local

    <Directory /var/www/verify_bot_api/src/app/>
        Order deny,allow
        Allow from all
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/gargarsa.sms.local-error.log
    LogLevel debug
    CustomLog ${APACHE_LOG_DIR}/gargarsa.sms.local-access.log combined
</VirtualHost>

but no avail.

I tried running gunicorn via a screen session but I couldn’t access it either.

I tried running it programmatically as such but no avail:

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

I understand this is a very broad way to ask, but I’m truly stumped.

How do I run an api built using fastapi on Apache2?

Thank you for your assistance.

2

Answers


  1. Chosen as BEST ANSWER

    Just incase anybody else stumbles on here, this is what I did and this is how it worked for me. This came about b/c there was not a lot of information on the web -- that I could find -- in regards to deploying fastapi on linux -- specifically ubuntu 18.04.4 -- with apache2 and no other things. When I say no other thing, I mean docker, caddy, or whatever of the sorts.

    The usual things must be done before hand, these are:

    1. create the db the api will use
    2. install the virtual environment
    3. install the necessary dependencies from requirements.txt
    4. either scp or clone from github the production code of the api
    5. place the production code of the api in the /var/www/
    6. you can use gunicorn to be the actual server while apache is a reverse proxy that can connect you to it (remember to cd into the actual directory that contains the module 1st also to use screen with it)
    7. set up apache2 as a reverse proxy by "a2enmod proxy proxy_ajp proxy_http rewrite deflate headers proxy_balancer proxy_connect proxy_html"
    8. actually type up the server conf file and enable it (sample provided at the bottom)
    9. ALLWAYS MAKE BACKUPS

    Reference: https://www.vioan.eu/blog/2016/10/10/deploy-your-flask-python-app-on-ubuntu-with-apache-gunicorn-and-systemd/

    Functioning Sample apache conf file:

    <VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com
    
        ServerName server-name
        ServerAdmin webmaster@localhost
        ServerAlias server-alias
        
        #DocumentRoot /document/root/
    
        <Proxy *>
            AuthType none
            AuthBasicAuthoritative Off
            SetEnv proxy-chain-auth On
            Order allow,deny
            Allow from all
        </Proxy>
    
        ProxyPass / http://127.0.0.1:port/
        ProxyPassReverse / http://127.0.0.1:port/
        #ProxyPass /api http://127.0.0.1:port/api
        #ProxyPassReverse /api http://127.0.0.1:port/api
    
        <Directory /document/root/>
            Order deny,allow
            Allow from all
        </Directory>
    
        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn
    
        ErrorLog ${APACHE_LOG_DIR}/server-error.log
        LogLevel debug
        CustomLog ${APACHE_LOG_DIR}/server-access.log combined
    
        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
    </VirtualHost>
    

    To run the actual api:

    gunicorn api:app -w 1 -k uvicorn.workers.UvicornWorker -b "127.0.0.1:port"
    

    Edit: I have not placed any security mechanism at all here


  2. WSGI servers is not compatible with FastAPI, FastAPI only runs in ASGI server, gunicorn and all the other WSGI servers just implements PEP Standards with ASGI workers in depth they still work as ASGI with the workers.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search