I'm trying to create a stackdriver webhook listener in google cloud functions, using the following script:
import sys
import logging
import json
from flask import Flask
from flask import Response, request
def webhook(request):
logging.info("Stackdriver ga360_merge_ready starting up on %s" % (str.replace(sys.version, '\n', ' ')))
app = Flask(__name__)
#app.route('/', methods=['POST'])
def simple_handler():
""" Handle a webhook post with no authentication method """
json_data = json.loads(request.data)
logging.info(json.dumps(json_data, indent=4))
return Response("OK")
For the above, I have the following URL:
https://xxxxx.cloudfunctions.net/webhook
"webhook" is the cloud functions name. when I put this URL in with an ending slash, as per the code, it doesn't seem to send across the message in from stackdriver, essentially, I want the message to also come through, presently, all I get is the below three log entries:
Not sure what I'm missing, I'm new to the python/webhooks world
Your simple_handler is never being called because the request is never being routed to the app you've created.
Is there a reason your function is set up like that? I would expect it to be something like this instead:
import sys
import logging
import json
logging.info("Stackdriver ga360_merge_ready starting up on %s" % (str.replace(sys.version, '\n', ' ')))
def webhook(request):
""" Handle a webhook post with no authentication method """
logging.info(json.dumps(request.get_json(), indent=4))
return Response("OK")
Related
I am building a rest api with fastapi. I implemented the data layer separately from the fastapi application meaning I do not have direct access to the database session in my fastapi application.
I have access to the storage object which have method like close_session which allow me to close the current session.
Is there a equivalent of flask teardown_request in fastapi?
Flask Implementation
from models import storage
.....
.....
#app.teardown_request
def close_session(exception=None):
storage.close_session()
I have looked at fastapi on_event('shutdown') and on_event('startup'). These two only runs when the application is shutting down or starting up.
We can do this by using dependency.
credit to williamjemir: Click here to read the github discussion
from fastapi import FastAPI, Depends
from models import storage
async def close_session() -> None:
"""Close current after every request."""
print('Closing current session')
yield
storage.close()
print('db session closed.')
app = FastAPI(dependencies=[Depends(close_session)])
#app.get('/')
def home():
return "Hello World"
if __name__ == '__main__':
import uvicorn
uvicorn.run(app)
use fastapi middleware
A "middleware" is a function that works with every request before it is processed by any specific path operation. And also with every response before returning it.
It takes each request that comes to your application.
It can then do something to that request or run any needed code.
Then it passes the request to be processed by the rest of the application (by some path operation).
It then takes the response generated by the application (by some path operation).
It can do something to that response or run any needed code.
Then it returns the response.
Example:
import time
from fastapi import FastAPI, Request
app = FastAPI()
#app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# do things before the request
response = await call_next(request)
# do things after the response
return response
references:
https://fastapi.tiangolo.com/tutorial/middleware/
I was trying to make a slack bot using slackeventsapi running on ngrok for now.
It can send messages properly but slack events adaptor doesn't seem to be working properly. It gives the code 200 every time a message is sent but the payload doesn't come. I tried printing it but the printing it shows nothing.
There was another post asking a similar question whose solution in the end was to make a new app on slack API but it doesn't seem to fix my issue. I have made another app but the issue persists.
I was following a tutorial so I have tried to match his code exactly but it doesn't seem to work even then. In case it will be helpful - https://www.youtube.com/watch?v=6gHvqXrfjuo&list=PLzMcBGfZo4-kqyzTzJWCV6lyK-ZMYECDc&index=2.
The slack API scopes
Slack API Subscriptions
import slack
import os
from pathlib import Path
from dotenv import load_dotenv
from flask import Flask
from slackeventsapi import SlackEventAdapter
env_path = Path('.')/'.env'
load_dotenv(dotenv_path=env_path)
client = slack.WebClient(token=os.environ['TEST2_SLACK_TOKEN'])
BOT_ID = client.api_call("auth.test")['user_id']
app = Flask(__name__)
slack_event_adaptor = SlackEventAdapter(os.environ['SIGNING_SECRET2'], '/slack/events', app)
client.chat_postMessage(channel=f'#new', text="Hello")
if __name__ == "__main__":
app.run(debug=True)
#slack_event_adaptor.on('message')
def message(payload):
print(payload)
event = payload.get('event',{})
channel_id = event.get('channel')
user_id = event.get('user')
text = event.get('text')
if BOT_ID != user_id:
client.chat_postMessage(channel= channel_id, text = text)
I had similar problem when I used slack_event_adaptor and then I tried slack_bolt and everything works well. Let me share example you may try if you want:
import re
from config import config
from flask import Flask, request
from slack_sdk import WebClient
from slack_bolt import App
from slack_bolt.adapter.flask import SlackRequestHandler
app = Flask(__name__)
slack_token = config.slack_token
client = WebClient(slack_token)
bolt_app = App(token=slack_token, signing_secret=config.signing_secret)
handler = SlackRequestHandler(bolt_app)
#bolt_app.message(re.compile("Hello bot",re.IGNORECASE))
def reply_in_thread(payload: dict):
""" This will reply in thread instead of creating a new thread """
response = client.chat_postMessage(channel=payload.get('channel'),
thread_ts=payload.get('ts'),
text=f"Hello<#{payload['user']}>")
#app.route("/datalake/events", methods=["POST"])
def slack_events():
""" Declaring the route where slack will post a request """
return handler.handle(request)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
When you write "Hello bot" bot will respond you accordingly.
I am trying to build a simple flask api to post json data to a list (eventually with be redshift but this is just a simple test program).
I have attached the api code first followed by the code to send data.
I am getting internal server error issues when running the second script.
The code seems very simple though and I cannot figure out what is wrong.
from flask_restful import Api, Resource
from flask import request
app = Flask(__name__)
api = Api(app)
audit_log = []
class audit(Resource):
#def get (self):
#return {"data":"HelloWorld"}
def put (self):
new_item = request.get_json()
audit_log.append(new_item)
return new_item
api.add_resource(audit,"/")
app.run()
import requests
BASE = "HTTP://127.0.0.1:5000/"
response = requests.put(BASE, params = {'auditid' : 'xyz', 'jobname' : 'abc'})
print (response.json())
It seems that you haven't imported the Flask properly
instead of this
from flask import request
use this
from flask import Flask, request
This should work fine...
I have tried a lot of things but nothing is working. It always gives me the "Incomplete response received from application" message in the navigator.
My code is:
import sys
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def application():
uri = request.args.get('url')
message = 'It works!\n'
response = '\n'.join([message, uri])
return response
The problem is or in the #app.route('/') line or in the uri = request.args.get('url').
I just want to call the with the navigator like http://example.com/script/?url=hello.
I tried changing #app.route('/') to #app.route('/script') and #app.route('/script/') but nothing is working... any ideas?
Thanks a lot!
For future readers: note that the original question has been edited in response to this suggestion.
First issue: You seem to be using some very low-level WSGI implementation when Flask does a lot of the sugar for you. Consider testing with a function that lets Flask do the work and then expand as needed.
import sys
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def test():
uri = request.args.get('url')
message = 'It works!\n'
version = 'Python %s\n' % sys.version.split()[0]
response = '\n'.join([message, version, uri])
return response
Next, keep in mind that Flask wants a string return type. If you want to pass a data structure back, consider jsonify.
I am making a simple function to check a URL status and redirect on 404. This app works fine in Flask localhost but when I move this to Google Cloud Functions, I keep getting "Error: could not handle the request". This is when my parameters on both the Cloud Function and the localhost are the exact same.
Am I doing something wrong with importing 'redirect' from Flask?
GCLOUD CODE: NOT WORKING
from flask import Flask, redirect
from flask import request
import requests
def urlincoming():
custID = request.args['custID']
token = request.args['token']
custEmail = request.args['custEmail']
storeDomain = request.args['domain']
adminEmail = request.args['adminEmail']
baseUrl = f"{storeDomain}/account/reset/{custID}/{token}"
baseUrlFailedAuth = f"{storeDomain}/account/invalid_token"
requestBaseUrl = requests.head(baseUrl)
if(requestBaseUrl.status_code == 200):
return redirect(baseUrl)
else:
return redirect(baseUrlFailedAuth)
LOCALHOST CODE: WORKING
from flask import Flask, redirect
from flask import request
import requests
app = Flask(__name__)
#app.route('/urlincoming')
def urlincoming():
custID = request.args['custID']
token = request.args['token']
custEmail = request.args['custEmail']
storeDomain = request.args['domain']
adminEmail = request.args['adminEmail']
baseUrl = f"{storeDomain}/account/reset/{custID}/{token}"
baseUrlFailedAuth = f"{storeDomain}/account/invalid_token"
requestBaseUrl = requests.head(baseUrl)
if(requestBaseUrl.status_code == 200):
return redirect(baseUrl)
else:
return redirect(baseUrlFailedAuth)
All Google Cloud Functions need to have one of the following two signatures:
HTTP Functions:
function_name(request):
...
Background functions:
function_name(data, context):
...
Depending on the type of function you're creating, you either need to add the request or data, context arguments.
from flask import redirect
import requests
def urlincoming(request):
I was able to fix things by adding the request as a argument but I'm not sure why it worked :/