1

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)

1 Answer 1

0

Well, after a week of headbanging. I think I figured it out. The dash app requires the Procfile to point to the entry way for the Gunicorn server.

web: gunicorn your_module_name:server

However, for a flask app, the Procfile requires:

web: gunicorn your_module_name:app

It seems that running the dash app prevents the flask API from working. Don't try both boys and girls.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.