Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use nginx as the web service, instead of flask's app.run #1389

Open
micahflee opened this issue Aug 15, 2021 · 2 comments
Open

Use nginx as the web service, instead of flask's app.run #1389

micahflee opened this issue Aug 15, 2021 · 2 comments

Comments

@micahflee
Copy link
Collaborator

Right now when OnionShare starts a web service, it uses app.run to start it directly in flask. I think instead we should launch an nginx subprocess and use that along with gunicorn to host the flask app.

Before implementing this, I'm not sure how a few things will work:

  • Progress bars. If someone downloads a file from nginx, how can we hook into the real-time file transfer to make progress bars work?
  • "Stop sharing after files have been sent". How do we know that the files are finished sending?
@micahflee
Copy link
Collaborator Author

We should run a single nginx process on launch, and update the nginx config and reload while using the app, each time a service is started or stopped. We can reload the nginx config using an OS signal: https://nginx.org/en/docs/control.html

For monitoring progress of downloads and uploads from nginx, we might need a custom nginx module. Like, maybe this, except with download support too: https://github.com/masterzen/nginx-upload-progress-module

@micahflee
Copy link
Collaborator Author

This is going to be trickier than I first realized. I'm working in the nginx branch (https://github.com/onionshare/onionshare/tree/nginx) and I've successfully made the CLI version run an nginx process in the background, with the ability to add and remove vhosts.

Next I'm trying to refactor onionshare_cli/web/web.py's start and stop functions to run the web apps in gunicorn, instead of just running self.app.run().

But it turns out, this means running gunicorn subprocesses, and each of those need to run their own subprocesses for each flask app, as opposed to running all of the flask apps in the main onionshare process like it works now.

To run gunicorn you need a subprocess like this:

gunicorn --bind=127.0.0.1 --workers=2 wsgi:application

The wsgi:application part looks for a module called wsgi.py with application inside of being the flask app.

A typical wsgi.py application might looks like this, in this case importing the flask app app from app.py:

from app import app as application

Right now OnionShare defines a web object, which includes the flask app, and then calls a bunch of functions to modify the flask app (define routes depending on the mode, etc.), and then runs app.run() to start the server. This needs to be refactored a bunch of make it possible to run an individual onionshare mode server as a subprocess.

Like, maybe instead of creating a Web object in the onionshare-cli process, we need a wsgi.py and that creates the Web object and defines the flask server based on information in environment variables (what mode, port, password, etc.). And then instead of calling web.start(), we launch a new gunicorn subprocess with the correct environment, which runs wsgi.py, which creates the actual web service we want. And to stop it, we send a signal to the gunicorn process to halt.

But if these are all running in different processes now, how can we communicate between the flask apps and the onionshare GUI? Now we have to deal with inter-process communication...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant