Uso MKdocs para crear una documentación muy confidencial y quiero que esté disponible en línea de forma segura.
mi proyecto es:
(de esta manera no hay datos claros persistentes en el servidor)
La documentación se edita solo localmente, se cifra y se sincroniza con el servidor.
Ahora, estoy bloqueado en el sitio de servicio en el paso del matraz, porque el sitio de MKdocs está estructurado así:
├── 404.html ├── documentation │ ├── Folder 1 │ │ ├── Sub folder 1 │ │ │ └── index.html │ │ └── Sub Folder 2 │ │ └── index.html │ ├── Folder 2 ├── css │ └── ... ├── fonts │ └── ... ├── img │ └── ... ├── index.html ├── js │ └── ... ├── search │ └── ... └── ... Traté de poner este contenido en ./static/site/ y luego reemplacé todos los enlaces href y src locales con el matraz
{{ url_for('static', filename='site/[original_content]) }}Pero por lo que puedo decir, no puede funcionar en una llamada estática como
app.send_static_file('site/index.html') Porque no hay reemplazo de contenido {{ .. }} (y esperaba este problema, es una página estática).
La pregunta: ¿Hay alguna manera de servir un sitio estático con una estructura "compleja" como esta, con matraz?
MÁS y no información necesaria, ¡el spoiler no es parte de la pregunta!:
En la medida en que pudiera aceptar cualquier sugerencia sobre cómo hacer todo de manera diferente, ahora me gustaría lograrlo.
Otra solución que pensé:
- sirviendo con nginx el sitio web estático, en una carpeta vacía, donde el frasco con la mecánica anterior descifraría el volumen. No sé cómo detectar el final de la sesión de nginx para volver a cifrar.
- Condensar TODA la estructura en un solo gran archivo HTML. Esto sería increíble , pero realmente perdí demasiado tiempo buscando e intentando, pero... no tuve suerte en mi investigación. (pero esta sería mi solución referida)
Podemos considerar las páginas HTML renderizadas de MkDocs como simples plantillas Flask. Entonces, todo lo que tenemos que hacer es crear un punto final de Flask que primero verifique los permisos y luego, según la URL, sirva el archivo HTML de MkDocs renderizado o un archivo estático relacionado.
Llamemos a nuestro nuevo bridge de punto final. Primero, coloque todo, desde el directorio del site de MkDocs hasta el directorio templates/bridge de Flask. Mi árbol de MkDocs de ejemplo se ve así:
$ tree templates/bridge templates/bridge ├── 404.html ├── css │ ├── base.css │ ├── bootstrap.min.css │ └── font-awesome.min.css ├── dir1 │ ├── sub1 │ │ └── index.html │ └── sub2 │ └── index.html ├── dir2 │ ├── sub1 │ │ └── index.html │ └── sub2 │ └── index.html ├── fonts │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── img │ ├── favicon.ico │ └── grid.png ├── index.html ├── js │ ├── base.js │ ├── bootstrap.min.js │ └── jquery-1.10.2.min.js ├── search │ ├── lunr.js │ ├── main.js │ ├── search_index.json │ └── worker.js ├── sitemap.xml └── sitemap.xml.gz Y nuestro nuevo punto final bridge Flask:
from flask import Flask, render_template, send_from_directory app = Flask(__name__) @app.route('/bridge/') @app.route('/bridge/<path:p1>/') @app.route('/bridge/<path:p1>/<path:p2>/') @app.route('/bridge/<path:p1>/<path:p2>/<path:p3>/') def bridge(p1=None, p2=None, p3=None): # Permissions checking... # Serve MkDocs's static files requested from CSS files if p1 == 'css' and p2 in ('img', 'fonts'): # CSS fix, eg /bridge/css/img/example.png -> /bridge/img/example.png return send_from_directory(f'templates/bridge/{p2}/', p3) # Serve MkDocs's static files if p1 in ('css', 'js', 'fonts', 'search'): return send_from_directory(f'templates/bridge/{p1}/', p2) # Serve rendered MkDocs HTML files if p3 != None: template = f'bridge/{p1}/{p2}/{p3}/index.html' elif p2 != None: template = f'bridge/{p1}/{p2}/index.html' elif p1 != None: template = f'bridge/{p1}/index.html' else: template = 'bridge/index.html' return render_template(template) Como puede ver, creamos un par de definiciones de ruta. Dado que MkDocs usa rutas relativas en todas partes, la ruta de URL dir1/sub1/ en MkDocs se convertirá en https://yoursite.com/bridge/dir1/sub1/ para que podamos capturarlos con este esquema de enrutamiento de URL y las partes de URL aterrizarán en p1 , p2 , p3 variables de ruta que usaremos para servir el contenido correspondiente.
Hay dos tipos de contenido: archivos estáticos (por ejemplo, archivos CSS o imágenes) y archivos de contenido HTML. Los archivos estáticos estarán en el directorio css , js , images , fonts , etc., por lo que cuando p1 es igual a uno de estos, usamos la función send_from_directory de Flask para atenderlos. Los archivos estáticos a los que se hace referencia desde archivos CSS deben tener un tratamiento específico porque MkDocs también usa rutas relativas allí.
Y para los archivos index.html renderizados, solo necesitamos determinar el nivel de anidamiento en función de la ruta y devolver el archivo index.html seleccionado como una plantilla Flask normal. Dado que MkDocs usa URL relativas, no tenemos que modificar nada en los archivos HTML representados, cada URL recibirá el prefijo /bridge/ , por lo que podemos servirlos con nuestro punto final de bridge .
Debe realizar la verificación de permisos al comienzo del bridge (o como decorador, según su solución). Es posible que deba agregar variables de ruta p4 y/o p5 si tiene un contenido anidado más profundo, pero es una extensión directa de mi ejemplo.
Nota: Flask también servirá la página de error 404.
Tuve muchos problemas con su código, lo redirigí a /bridge/index.html después de descifrar, y todo lo que hiciera clic a partir de ahí comenzaría con /bridge /index.html/resource/p1/p2/etc..
Después de eso, tuve que reconsiderar dónde estaban p1, p2 y demás, la solución que encontré BASADA totalmente en la solución de Dauros, que realmente me gusta es:
@app.route('/<path:p1>/') @app.route('/<path:p1>/<path:p2>/') @app.route('/<path:p1>/<path:p2>/<path:p3>/') @app.route('/<path:p1>/<path:p2>/<path:p3>/<path:p4>/') @app.route('/<path:p1>/<path:p2>/<path:p3>/<path:p4>/<path:p5>/') @app.route('/<path:p1>/<path:p2>/<path:p3>/<path:p4>/<path:p5>/<path:p6>/') def bridge(p1=None, p2=None, p3=None, p4=None, p5=None, p6=None): # Permissions checking... # I'm planning on using basic auth from nginx to even try to show a page resource = '/'.join([p for p in (p1,p2,p3,p4,p5,p6) if p]) the_file = resource.split('/')[-1] the_path = '/'.join(resource.split('/')[:-1]) if p1 in ('css', 'fonts', 'img', 'js', 'search'): return send_from_directory(f'templates/bridge/{the_path}/', the_file) else: template = f'bridge/{resource}/index.html' return render_template(template) @app.route('/', methods=HTTP_METHODS) def home(): method = request.method if method == "GET": # TO BE CHANGED, checking if volume is already decrypted. if os.path.exists(f"{BASE_FODLER}/locked"): # decrypt page resp = make_response(render_template('decrypt.html')) return resp else: template = 'bridge/index.html' return render_template(template) elif method == "POST": if 'password' in request.form: decrypt_key = request.form['password'] # decryption omitted template = 'bridge/index.html' return render_template(template) else: return not_allowed_ans() else: return not_allowed_ans() return SendOk() Como puede ver, desde la parte inferior, template = 'bridge/index.html' y luego return render_template(template) traiga el sitio del puente a la raíz mystime.com/ esto significa que toda la ruta debe ser raíz.
Cualquier "enlace" será entonces: mysite.com/folder_1/sub_folder_1/index.html
Después de eso, simplifiqué para mí agregar pX en el futuro (sería bueno una sola ruta con PX dinámicos, PERO, ¡esto es suficiente para una documentación estática!)