I'm trying to build a quick and simple webpage to test an HTTP Requests service that I'm building, and Flask seems to be making it way harder than it should be. All I want is to display any incoming HTTP Requests on the page, and then return the received payload to the service that called the webpage.
Copying the Flask tutorial (plus the code for collecting HTTP requests) left me with this app.py
file:
from flask import Flask, request, abort, jsonify, render_template, Response, stream_with_context, url_for, redirect
app = Flask(__name__, template_folder = '')
responses = []
@app.route('/')
def index():
return render_template('index.html', resps = responses)
@app.route('/request', methods = ['GET', 'POST'])
def add_message():
print("Request dictionary: {}".format(request.json))
responses.append(request.json)
return redirect('')
app.run(host = '0.0.0.0', port = 81, debug = True)
I understand that request.json
does not actually display all of the incoming data, but that is easily solvable assuming that the dynamic display of requests is at all possible.
And here's my index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask Response Test Page</title>
</head>
<body>
Web App with Python Flask!<br><br>
<label id="value_lable">
{% for resp in resps %}
{{ resp }}<br>
{% endfor %}
</label>
</body>
</html>
My service that sends Python requests is really simple and works great. Basically, users type in the endpoint, payload, and output variable, and my service will send the request to endpoint
and store the response in variable
. I know it works because I can reload my Flask test page and it will show the list of received requests, and my service is printing out the input JSON as the request response. This code runs inside a Docker container so I am using http://host.docker.internal:81/request
as my endpoint for the purposes of this test as per this answer.
import requests
class JSONGETRequest():
def on_start(self, executive):
# dict.get() returns None if the dict doesn't have the requested key
endpoint = self.node.data.get("url")
payload = self.node.data.get("payload")
variable = self.node.data.get("variable")
out = requests.get(endpoint, json = payload, headers = {"User-Agent": ""}).json()
executive.set_context(variable, out)
executive.next(self.node, "output_1")
TL;DR:
I've tried a bunch of different answers posted on StackOverflow that are related to this question and none of them worked. Everything after this is the various things I tried already.
I attempted to use this page (Flask Dynamic data update without reload page) but that uses a button to force the page to reload, and I cannot find anything that indicates AJAX can activate/run a function whenever the page receives a Request. The vast majority of questions I've found relating to "flask update page data without refresh" all use a button but I really just want a streamed output of the requests as they come in.
Edit: Based on NoCommandLine's comment I was able to fix my implementation of this answer, but it still fails to update the page in real-time, and requires a page reload in order to update the displayed data.
I tried to use this answer ~~but got the error werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'request'. Did you mean 'static' instead?
when using~~ with the following code:
@app.route('/requests', methods = ['GET', 'POST'])
def add_message():
print("Request dictionary: {}".format(request.json))
responses.append(request.json)
def inner():
# simulate a long process to watch
for i in responses:
# this value should be inserted into an HTML template
yield i + '<br/>\n'
return Response(inner(), mimetype = 'text/html')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask Response Test Page</title>
</head>
<body>
Web App with Python Flask!<br><br>
<div>
<!-- url_for() is based off of the target method name, not the page name-->
<iframe frameborder="0"
onresize="noresize"
src="{{ url_for('add_message')}}"
style='background: transparent; width: 100%; height:100%;'>
</iframe>
</div>
</body>
</html>
~~Which honestly makes no sense since the request
page should exist since I created the @app.route('/request')
- it fails with both url_for('request')
and url_for('/request')
.~~
Supposedly there is "quite a few tutorials" on how to use AJAX but not a single on that I've found that even MENTIONS HTTP requests.
How is there not a website or service that already does this? Just take in any incoming requests and print them out. There's no reason this should be this hard.
I tried using @app.after_request
but it seems to be useless. And for some reason render_template
is just a completely useless function that does absolutely nothing helpful:
@app.route('/request', methods = ['GET', 'POST'])
def add_message():
print("Request dictionary: {}".format(request.json))
responses.append(request.json)
return request.json
@app.after_request
def update(response):
render_template('index.html', resps = responses)
return response
This question is basically a duplicate but has no (useful) answers.