Skip to content
Snippets Groups Projects
server.py 2.81 KiB

from flask import Flask, Response, request, send_from_directory
from flask_cors import CORS 
from urllib.parse import urlparse
import sys, requests

app = Flask(__name__)

VERSION = '1.1.0'

FLASK_RUN_PORT = sys.argv[1]
DATA_PATH = sys.argv[2]
FLASK_ENV = sys.argv[3]
FLASK_DEBUG = sys.argv[4]

app = Flask(__name__, static_url_path='')
app.url_map.strict_slashes = False
CORS(app)

'''
=================== URLs for Web Apps ======================
Works for any numbers of sub paths
'''
@app.route('/<p1>', methods=['GET'])
@app.route('/<p1>/<path:p2>', methods=['GET'])
def x(p1, p2=''):
    path = p1
    if p2:
        path = path + '/' + p2
    app.logger.debug('[path] ' + path)
    return send_from_directory(DATA_PATH, path)

'''  
=================== Proxy for CouchDB access ==============
The following works like a proxy server:

A flask server URL of the form 
  "http://127.0.0.1:8081/xxxx/vl_db/000_SERVERS" 
will be forwarded to the real CouchDB URL 
  "http://127.0.0.1:xxxx/vl_db/000_SERVERS"

The part 'xxxx' can be any integer as a future port address for couchdb.

see:
https://stackoverflow.com/questions/6656363/proxying-to-another-web-service-with-flask 
'''
@app.route('/<int:real_port>/', \
  methods=['GET','PUT','POST','HEAD','DELETE','OPTIONS']) 
@app.route('/<int:real_port>/<path:p>',
  methods=['GET','PUT','POST','HEAD','DELETE','OPTIONS']) 
def couchdb_proxy(real_port, p=''):
    q = request.query_string.decode();
    path = p
    if q:
        path = path + '?' + q
    host = urlparse(request.base_url).hostname
    scheme = urlparse(request.base_url).scheme
    new_url = '{}://{}:{}/{}'.format(scheme, host, real_port, path) 
    app.logger.debug('[old couchdb url] ' + request.url)
    app.logger.debug('[new couchdb url] ' + new_url)
    resp = requests.request(
        method=request.method,
        url=new_url,
        headers={key: value for (key, value) in request.headers if key != 'Host'},
        data=request.get_data(),
        cookies=request.cookies,
        allow_redirects=False)      
    excluded_headers = ['content-encoding', 'content-length', \
      'transfer-encoding', 'connection']
    headers = [(name, value) for (name, value) in resp.raw.headers.items()
               if name.lower() not in excluded_headers]
    response = Response(resp.content, resp.status_code, headers)
    return response  

@app.route('/')
@app.route('/index.html')
def home():
    return '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Webapps Deliverer</title>
</head>
<body>
   <h3>VacLab: Combined web and CouchDB proxy service</h3>Version: {}
</body>
</html>'''.format(VERSION)
    
@app.route('/version')
def version():
    return VERSION + '\n'
    
if __name__ == '__main__':
    app.config['ENV'] = FLASK_ENV
    app.config['DEBUG'] = FLASK_DEBUG
    app.run(host='0.0.0.0', port=FLASK_RUN_PORT)