How to programmatically communicate with Apache? - python

So many web applications these days run on their own microservers, it can be hard to implement them on shared hosting platforms. The apps listen on a dedicated port you can customize or reverse proxy, but shared hosting usually only has 80 and 443 open.
Just as an example, the handy web-based editor ICEcoder is a PHP application, so you just drop the files in a directory and away you go. However, the Cloud9 editor runs its own server. You can customize the port, but again, you cant run the reverse proxy.
I had the idea of using a PHP or Python CGI script as an intermediary. Something like:
www.mydomain/mydirectory/middleman.py
from BaseHTTPServer import BaseHTTPRequestHandler
import urlparse, json
# hpyothetical apache api
import apache
parsed_path = urlparse.urlparse(self.path)
response = apache(url=parsed_path, port=8080)
sendStuffBack(response)
Would this be possible with Apache? How would I implement it?
Edit:
Here is what I did based on #grawity's answer.
helloflask.py
#!/usr/bin/env python
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
middle.py
#!/usr/bin/env python
print ("Content-Type: text/html")
print()
import requests
#response = requests.get("http://localhost:5000")
response = requests.get("http://localhost:8888/token=8a387fe88d662e2568f9b8ec2398191452492e7184536670")
print(response.text)

Your Python project is a reverse proxy, and the API you're looking for is just ordinary HTTP. (After all, that's how web browsers interact with Apache already...)
To make HTTP requests, you need a client like urllib or requests:
import requests
response = requests.get("http://" + apache_host + ":8080/" + parsed_path)
By default, all your apps and microservers will think that all clients come from localhost. If that's a problem, see if your apps accept the X-Forwarded-For header. (If they do, include it in all your requests.)

Related

How to change the Redirect URI from HTTP to HTTPS within a FastAPI web app using fastapi_msal?

I am trying to setup Azure AD authentication for a web application using FastAPI. I am using the fastapi_msal python package to do this. The problem I am having is that when I go to the web app, I am able to login, but once i am authenticated, it says the redirect URI that the application is using begins with HTTP. However, Azure requires the redirect uri begin with HTTPS unless running the app locally. Does anyone know how I can change the redirect uri to begin with https instead?
The code for my project pretty much exactly resembles the code from this example project here. However, I have found a similar project using Flask instead of FastAPI. And there is a specific portion of the code that addresses this redirect uri problem:
# This section is needed for url_for("foo", _external=True) to automatically
# generate http scheme when this sample is running on localhost,
# and to generate https scheme when it is deployed behind reversed proxy.
# See also https://flask.palletsprojects.com/en/1.0.x/deploying/wsgi-standalone/#proxy-setups
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
Does anyone know how I can do something like this for a web app using FastAPI instead?
The full source code for the Flask app can be found here

Flask Server not responding to HTTP POST Request

I built a simple flask server in order to automate python scripts based on an HTTP POST Request coming in from an outside service. This service sends these requests in response to events that we have created based on data conditions. All the flask server needs to do is parse the requests, and take the numerical value stored in the request and use it to run the corresponding python script. At one point, this system was working consistently. Fast forward a few months, the server was no longer working when tried again. No changes were made to the code. According to wireshark, The computer hosting the flask server is receiving the request to the correct port, but the request is now timing out. The host system is failing to respond to the request. Any Idea what is going on here? The firewall has temporarily been turned off.
Alternatively, is there another better package to achieve this goal with?
from flask import Flask, request
import threading
import runpy
app = Flask(__name__)
#app.route('/', methods=['POST'])
def PostHandler():
directory = {}
with open(r"M:\redacted") as f:
for line in f:
(key,val) = line.split()
directory[int(key)] = val
print(directory)
path = r"M:\redacted"
content = request.json
content = content['value']
print(content)
sel_script = int(content)
print(directory[sel_script])
runpy.run_path(path_name=path + directory[sel_script])
return
app.run(host="10.244.xx.xx", port=8080, threaded=True)

Using flask to return server side processed URL

I am hosting my web app on my in-house server using flask (100% accessible online - running on host 0.0.0.0), however, I am trying to use flask to navigate to other locally hosted web apps while browsing from a public network .. is it possible? i.e. onclick() i would like to redirect to URLs that are only available on the local network .. is this possible? I am essentially looking to use my flask app to access my LAN .. thanks!
from flask import Flask, redirect
app = Flask(__name__)
#app.route('/<ip>')//local ip
def redirect_to_link(ip):
return redirect('ip') #would like this to be processed server side and displayed through flask
If the other apps are accessible from extern , yes , you can. If not , you can try serving other app pages by making a request to your flask app first. Flask application should download the webpage for you and then serve it to you externally. Basically you want to make a proxy server.
Try this:
import requests
from flask import Flask, redirect
app = Flask(__name__)
#app.route('/<ip>')//local ip
def redirect_to_link(ip):
return redirect('ip') #would like this to be processed server side and displayed through flask
#local url address to serve examples:
#192.168.1.123:8888/whatyouwant
#192.168.1.123:5656/
#192.168.1.123/somepage
#192.168.1.123
#app.route('/lan/<url>')
def serve_from_lan(url):
r = requests.get("http://"+url, allow_redirects=True)
return r.content
So simple it's not secure but can do the job . then you can think about security.
Also consider that all the addresses present in the application pages in lan should refer to your flask app to be navigable-

Is http call significantly slower than local call generally and particularly in Flask?

I have a python library and need to provide services for others to use. Since the local installation is not a simple 'pip install ...' to complete, I want to set up a http service in Flask so users don't need to locally install it.
If the http server is very close to users' machines, I have a couple of questions to ask, since I am new to http service:
Is http call significantly slower than local call?
In local calls, my api can process texts (large amount of plaint text) in batches to speed up, instead of one by one processing. But the typical http service receives one text, process it and return it. Is that would be slower? Or the http client needs to write concurrent code to make http calls and the http service doesn't need to worry about any concurrency issue.
Is there any general method to speed up http service call?
My http service code would look like:
from flask import Flask
from flask import request
from flask import jsonify
api = Flask(__name__)
#api.route('/process', methods=['GET'])
def process():
text, stopwords = _parse_parameters()
pos = str(wlu.process(text, stopwords=stopwords))
return pos
def _parse_parameters():
text = request.args.get('text')
stopwords = request.args.get('stopwords')
return (text, stopwords)
if __name__ == '__main__':
#api.run(host='0.0.0.0', port='5000')
from waitress import serve
serve(api, host="0.0.0.0", port=5000)
EDIT:
'Local call' means users install the python library locally and do the typical importing of dependencies:
import my_library

Call a python function within a html file

Is there a way to call a python function when a certain link is clicked within a html page?
Thanks
You'll need to use a web framework to route the requests to Python, as you can't do that with just HTML. Flask is one simple framework:
server.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('template.html')
#app.route('/my-link/')
def my_link():
print 'I got clicked!'
return 'Click.'
if __name__ == '__main__':
app.run(debug=True)
templates/template.html:
<!doctype html>
<title>Test</title>
<meta charset=utf-8>
Click me
Run it with python server.py and then navigate to http://localhost:5000/. The development server isn't secure, so for deploying your application, look at http://flask.pocoo.org/docs/0.10/quickstart/#deploying-to-a-web-server
Yes, but not directly; you can set the onclick handler to invoke a JavaScript function that will construct an XMLHttpRequest object and send a request to a page on your server. That page on your server can, in turn, be implemented using Python and do whatever it would need to do.
Yes. If the link points to your web server, then you can set up your web server to run any kind of code when that link is clicked, and return the result of that code to the user's browser. There are many ways to write a web server like this. For example, see Django. You might also want to use AJAX.
If you want to run code in the user's browser, use Javascript.
There are several ways to do this, but the one that has worked best for me is to use CherryPy. CherryPy is a minimalist python web framework that allows you to run a small server on any computer. There is a very similiar question to yours on stackoverflow - Using the browser for desktop UI.
The code below will do what you want. Its example 2 from the CherryPy tutorial.
import cherrypy
class HelloWorld:
def index(self):
# Let's link to another method here.
return 'We have an important message for you!'
index.exposed = True
def showMessage(self):
# Here's the important message!
return "Hello world!"
showMessage.exposed = True
import os.path
tutconf = os.path.join(os.path.dirname(__file__), 'tutorial.conf')
if __name__ == '__main__':
# CherryPy always starts with app.root when trying to map request URIs
# to objects, so we need to mount a request handler root. A request
# to '/' will be mapped to HelloWorld().index().
cherrypy.quickstart(HelloWorld(), config=tutconf)
else:
# This branch is for the test suite; you can ignore it.
cherrypy.tree.mount(HelloWorld(), config=tutconf)
I personally use CherryPy in combination with several other modules and tools:
Mako (template library)
py2exe (convert into Windows executable)
GccWinBinaries (used in combination with py2exe)
I wrote an article about Browser as Desktop UI with CherryPy that introduces modules and tools used plus some further links that might help.
In addition to running Python scripts on a server, you can run Python scripts on the client-side using Skulpt.

Categories