I'm attempting to write my first API. I wrote (with help of GPT), a simple Request script and I uploaded the Dash-API script to Heroku. I'm getting input from multiple remote locations and I wish to add the remote data to a common Postgres database. I'm uncertain if Heroku dash-style app can be used as an API because of the various security layers in place. Is this even possible? I know Heroku has a platform API but it's intention is for other uses. So far, my error codes indicates the following so I'm uncertain if my approach is wrong or my code is wrong. Thank you.:
response content: b'<!doctype html>\n<html lang=en>\n<title>405 Method Not Allowed</title>\n<h1>Method Not Allowed</h1>\n<p>The method is not allowed for the requested URL.</p>\n'
import requests
data = {
"sensor": "temperature",
"value": 25.5
}
api_endpoint = 'https://my_app.herokuapp.com/ingest'
token = 'too_many_secrets'
headers = {'Authorization': f'Bearer {token}'}
response = requests.post(api_endpoint, json=data, headers=headers, verify=True)
if response.status_code == 200:
print("Data sent successfully")
else:
print(f"Failed to send data. Status code: {response.status_code}")
print(f'response content: {response.content}')
My Heroku API app
from flask import Flask, request, jsonify
from flask_cors import CORS
import dash
from dash import dcc, html, Input, Output
import json
app = Flask(__name__)
CORS(app)
dash_app = dash.Dash(__name__,)
server = dash_app.server
valid_tokens = ["too_many_secrets"]
dash_app.layout = html.Div(children=[
html.H1(children='Simple Dash App'),
dcc.Link('Ingest Data', href='/ingest'),
html.Div(id='output-message')
])
# Dash callback for the Dash route
@dash_app.callback(
Output('output-message', 'children'),
Input('url', 'pathname')
)
def display_page(pathname):
if pathname == '/ingest':
# This part is for Dash and the URL handling you've defined
return html.Div()
# Flask route for the traditional Flask endpoint
@app.route('/ingest', methods=['OPTIONS', 'POST'])
def handle_ingest():
if request.method == 'OPTIONS':
response = make_response()
response.headers.add('Access-Control-Allow-Origin', '*') # Adjust this to your needs
response.headers.add('Access-Control-Allow-Headers', 'Authorization, Content-Type')
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
return response
# Continue with your existing logic for POST requests
token = request.headers.get('Authorization')
if token in valid_tokens:
data = request.json # Assuming the data is sent as JSON
# Perform data validation and write to the database here
# Example: Write data to your Heroku Postgres database
print("Success: Data ingested successfully")
return jsonify({"message": "Data ingested successfully"})
else:
print("Unauthorized user: Your token was Invalid")
return jsonify({"message": "Unauthorized"}), 401
if __name__ == '__main__':
app.run(debug=True)