My @app.route decorator is not triggering its function

I am new to python and flask and I am encountering a problem with Flask. I am trying to use a local HTTP POST (webhook) to call a function from another file, but when I do nothing happens.

from flask import Flask
from BotSpeak import main

app = Flask(__name__)

@app.route('/', methods=['POST'])
def respond():
    main('hello')

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

This is my very basic Flask app. As you can see it is trying to call the main function from this file (BotSpeak):

from json import dumps
from httplib2 import Http

def main(botmsg):
    url = 'PLACEHOLDER FOR GOOGLE CHAT WEBHOOK URL'
    bot_message = {
        'text' : botmsg}

    message_headers = {'Content-Type': 'application/json; charset=UTF-8'}

    http_obj = Http()

    response = http_obj.request(
        uri=url,
        method='post',
        headers=message_headers,
        body=dumps(bot_message),
    )

    print(response)

if __name__ == '__main__':
    main("TEST MESSAGE")

This is the code that shoots local HTTP POSTs to my flask app:

import json
import requests

webhook_url ='http://127.0.0.1:5000/'

data = {PLACE HOLDER FOR JSON DATA}

r = requests.post(webhook_url, data=json.dumps(data), headers={'Content-Type': 'application/json'})

I can call the main function from other files outside the flask app and it'll work but it just wont trigger in the app.route decorator like it should. I really appreciate anyone's help and I encourage you to throw these into VS Code and try it for yourself.

1 answer

  • answered 2021-07-20 16:31 Iguananaut

    If you're using flask you don't have to manually construct an HTTP response using httplib2 unless you have some very specific use case.

    In your case you can just return bot_message since if the return value of a Flask handler is a dict it will convert it to a JSON response (including the correct headers). See

    https://flask.palletsprojects.com/en/2.0.x/quickstart/#about-responses

    In other words, your entire route handler could be rewritten (based off your example at least):

    @app.route('/', methods=['POST'])
    def respond():
        return {'text': 'hello'}
    

    If you want to pass the handling off to some utility function you can do that too, just make sure it returns a value, and that you in turn return an appropriate value from your respond() function.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum