#!/usr/bin/env python3 """ This is a demo application built using Flask-Gopher. Perhaps the easiest way to get up and running is: $ git clone https://github.com/michael-lazar/flask-gopher.git $ cd flask-gopher $ python3 -m virtualenv venv $ source venv/bin/activate $ pip install . $ ./demo/run_server.py Then, connect to the server with: $ lynx gopher://localhost:7005 """ import os import json from collections import OrderedDict from tabulate import tabulate_formats from pyfiglet import FigletFont from flask import Flask, request, abort, url_for, session from flask_gopher import make_gopher_ssl_server from flask_gopher import GopherRequestHandler, GopherExtension ROOT_DIR = os.path.dirname(__file__) app = Flask(__name__, static_url_path='') app.config.from_pyfile('demo.cfg') gopher = GopherExtension(app) @app.route('/') def index(): return gopher.render_menu_template('index.gopher') @app.route('/render-figlet') def figlet(): """ Render the search text using all possible figlet fonts. This loops through hundreds of fonts and may take a few seconds to return. """ text = request.environ['SEARCH_TEXT'] lines = [] for font in sorted(FigletFont.getFonts()): lines.extend(gopher.formatter.figlet(text, font=font).splitlines()) lines.append(font) lines.append('') return gopher.render_menu(*lines) @app.route('/render-tables') def tables(): """ Render an ascii table using all possible styles provided by tabulate. """ data = [ ('text', 'int', 'float'), ('Cell 1', 100, 1/3), ('Cell 2', -25, 0.001), ('Cell 3', 0, 0) ] lines = [] for table_fmt in tabulate_formats: lines.append(table_fmt) lines.append('') lines.append(gopher.formatter.tabulate(data, 'firstrow', table_fmt)) lines.append('\n') return gopher.render_menu(*lines) @app.route('/error/<int:code>/<path:path>') def error(code, path): """ Endpoint that simulates error behavior for different types of files. """ if code == 500: # Will raise a divide by zero error with a stack trace return 1 // 0 else: # Return the specified error code through flask abort(code) @app.route('/demo-links') def demo_links(): return gopher.render_menu_template('demo_links.gopher') # This example uses the app's static folder, but you can also point to any # absolute filepath that you want to serve files from. static_directory = gopher.serve_directory(app.static_folder, 'demo_directory', show_timestamp=True) @app.route('/demo-directory') @app.route('/demo-directory/<path:filename>') def demo_directory(filename=''): is_directory, file = static_directory.load_file(filename) if is_directory: return gopher.render_menu_template('demo_directory.gopher', filename=filename, listing=file) else: return file @app.route('/demo-errors') def demo_errors(): return gopher.render_menu_template('demo_errors.gopher') @app.route('/demo-session', defaults={'action': None}) @app.route('/demo-session/<action>') def demo_session(action): if action == 'create': session['id'] = request.environ['SEARCH_TEXT'] elif action == 'delete': session.clear() return gopher.render_menu_template('demo_session.gopher', action=action) @app.route('/demo-formatting') def demo_formatting(): table_data = [ ('text', 'int', 'float'), ('Cell 1', 100, 1/3), ('Cell 2', -25, 0.001), ('Cell 3', 0, 0) ] return gopher.render_menu_template('demo_formatting.gopher', table_data=table_data) @app.route('/demo-ssl') def demo_ssl(): secure = request.environ['SECURE'] return gopher.render_menu_template('demo_ssl.gopher', secure=secure) @app.route('/demo-environ') def demo_environ(): environ_table = [('Field', 'Value')] for key, val in sorted(request.environ.items()): if not key.startswith(('werkzeug', 'wsgi')): environ_table.append((key, val)) return gopher.render_menu_template('demo_environ.gopher', environ_table=environ_table) @app.route('/demo-form', defaults={'field': None}) @app.route('/demo-form/<field>') def demo_form(field): form_fields = OrderedDict([ ('first_name', 'First name'), ('last_name', 'Last name'), ('email', 'Email'), ('phone', 'Phone number'), ('address', 'Address') ]) # Check if there was a new field added to the request request_query = request.args.to_dict() if field in form_fields: request_query[field] = request.environ['SEARCH_TEXT'] # Build the form using the currently populated fields form = [] for name, description in form_fields.items(): if name in request_query: form.append('{:<13}: {}'.format(description, request_query[name])) else: url = url_for('demo_form', field=name, **request_query) form.append(gopher.menu.query('{:<13}:'.format(description), url)) # Add the buttons at the bottom of the form form.append('') if request_query: form.append(gopher.menu.dir('clear', url_for('demo_form'))) else: form.append('clear') if request_query.keys() == form_fields.keys(): url = url_for('demo_form', field='submit', **request_query) form.append(gopher.menu.dir('submit', url)) else: form.append('submit') # Show the query data if the "submit" button was pressed if field == 'submit': form.append('') form.append('Submitted form data:') form.append(json.dumps(request_query, indent=4, sort_keys=True)) form = '\r\n'.join(form) return gopher.render_menu_template('demo_form.gopher', form=form) if __name__ == '__main__': if app.config.get('SSL_CERTIFICATE_FILE'): ssl_context = ( app.config['SSL_CERTIFICATE_FILE'], app.config['SSL_CERTIFICATE_KEY_FILE']) server = make_gopher_ssl_server( host=app.config['HOST'], port=app.config['PORT'], app=app, threaded=app.config['THREADED'], processes=app.config['PROCESSES'], ssl_context=ssl_context, request_handler=GopherRequestHandler) server.serve_forever() else: app.run( host=app.config['HOST'], port=app.config['PORT'], threaded=app.config['THREADED'], processes=app.config['PROCESSES'], request_handler=GopherRequestHandler )