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

Fix JS Client when app is running behind a proxy #6863

Merged
merged 4 commits into from Dec 22, 2023

Conversation

freddyaboulton
Copy link
Collaborator

@freddyaboulton freddyaboulton commented Dec 21, 2023

Description

The issue is that we were constructing the URL manually but we can just use config.root which is the correct url hosting the gradio demo even if it's behind a proxy.

Closes: #6739
Closes: #6748

I tested several demos when running behind a local nginx reverse proxy

Vanilla Hello World

image

Custom Components Hello World

image

File Explorer

image

Iterator + Cancel

image

This is the nginx.conf

# nginx Configuration File
# https://www.nginx.com/resources/wiki/start/topics/examples/full/
# http://nginx.org/en/docs/dirindex.html
# https://www.nginx.com/resources/wiki/start/

# Run as a unique, less privileged user for security.
# user nginx www-data;  ## Default: nobody

# If using supervisord init system, do not run in deamon mode.
# Bear in mind that non-stop upgrade is not an option with "daemon off".
daemon off;

# Sets the worker threads to the number of CPU cores available in the system
# for best performance.
# Should be > the number of CPU cores.
# Maximum number of connections = worker_processes * worker_connections
worker_processes auto;  ## Default: 1

# Maximum number of open files per worker process.
# Should be > worker_connections.
# http://blog.martinfjordvald.com/2011/04/optimizing-nginx-for-high-traffic-loads/
# http://stackoverflow.com/a/8217856/2127762
# Each connection needs a filehandle (or 2 if you are proxying).
worker_rlimit_nofile 8192;

events {
  # If you need more connections than this, you start optimizing your OS.
  # That's probably the point at which you hire people who are smarter than
  # you as this is *a lot* of requests.
  # Should be < worker_rlimit_nofile.
  worker_connections 8000;
}

# Log errors and warnings to this file
# This is only used when you don't override it on a server{} level
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
error_log  var/log/nginx/error.log warn;

# The file storing the process ID of the main process
pid var/run/nginx.pid;


http {
  # Log access to this file
  # This is only used when you don't override it on a server{} level
  access_log var/log/nginx/access.log;

  # Hide nginx version information.
  server_tokens off;

  # Controls the maximum length of a virtual host entry (ie the length
  # of the domain name).
  server_names_hash_bucket_size 64;

  # Specify MIME types for files.
  include mime.types;
  default_type application/octet-stream;

  # How long to allow each connection to stay idle.
  # Longer values are better for each individual client, particularly for SSL,
  # but means that worker connections are tied up longer.
  keepalive_timeout 20s;

  # Speed up file transfers by using sendfile() to copy directly
  # between descriptors rather than using read()/write().
  # For performance reasons, on FreeBSD systems w/ ZFS
  # this option should be disabled as ZFS's ARC caches
  # frequently used files in RAM by default.
  sendfile on;

  # Don't send out partial frames; this increases throughput
  # since TCP frames are filled up before being sent out.
  tcp_nopush on;

  # Enable gzip compression.
  gzip on;

  # Compression level (1-9).
  # 5 is a perfect compromise between size and CPU usage, offering about
  # 75% reduction for most ASCII files (almost identical to level 9).
  gzip_comp_level 5;

  # Don't compress anything that's already small and unlikely to shrink much
  # if at all (the default is 20 bytes, which is bad as that usually leads to
  # larger files after gzipping).
  gzip_min_length 256;

  # Compress data even for clients that are connecting to us via proxies,
  # identified by the "Via" header (required for CloudFront).
  gzip_proxied any;

  # Tell proxies to cache both the gzipped and regular version of a resource
  # whenever the client's Accept-Encoding capabilities header varies;
  # Avoids the issue where a non-gzip capable client (which is extremely rare
  # today) would display gibberish if their proxy gave them the gzipped version.
  gzip_vary on;

  # Compress all output labeled with one of the following MIME-types.
  gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/ld+json
    application/manifest+json
    application/rss+xml
    application/vnd.geo+json
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/bmp
    image/svg+xml
    image/x-icon
    text/cache-manifest
    text/css
    text/plain
    text/vcard
    text/vnd.rim.location.xloc
    text/vtt
    text/x-component
    text/x-cross-domain-policy;
  # text/html is always compressed by gzip module

  # This should be turned on if you are going to have pre-compressed copies (.gz) of
  # static files available. If not it should be left off as it will cause extra I/O
  # for the check. It is best if you enable this in a location{} block for
  # a specific directory, or on an individual server{} level.
  # gzip_static on;

  include sites.d/*.conf;

server {
    listen 80;
    server_name subdomain.local;
    location /gradio-demo/ {  # Change this if you'd like to server your Gradio app on a different path
        proxy_pass http://127.0.0.1:7860/; # Change this if your Gradio app will be running on a different port
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location /custom-component/ {  # Change this if you'd like to server your Gradio app on a different path
        proxy_pass http://127.0.0.1:7861/; # Change this if your Gradio app will be running on a different port
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location /file-explorer/ {  # Change this if you'd like to server your Gradio app on a different path
        proxy_pass http://127.0.0.1:7862/; # Change this if your Gradio app will be running on a different port
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    location /cancel-events/ {  # Change this if you'd like to server your Gradio app on a different path
        proxy_pass http://127.0.0.1:7863/; # Change this if your Gradio app will be running on a different port
        proxy_buffering off;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

}

🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is an existing issue for this change. If not, please create an issue before you create this PR, unless the fix is very small.

Not adhering to this guideline will result in the PR being closed.

Tests

  1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up your Gradio environment locally and run the tests: bash scripts/run_all_tests.sh

  2. You may need to run the linters: bash scripts/format_backend.sh and bash scripts/format_frontend.sh

@gradio-pr-bot
Copy link
Contributor

gradio-pr-bot commented Dec 21, 2023

🪼 branch checks and previews

Name Status URL
Spaces ready! Spaces preview
Website ready! Website preview
Storybook ready! Storybook preview
Visual tests all good! Build review
🦄 Changes detected! Details

Install Gradio from this PR

pip install https://gradio-builds.s3.amazonaws.com/ee658cd0b5137ee656b20daa11837955cbcb418f/gradio-4.11.0-py3-none-any.whl

Install Gradio Python Client from this PR

pip install "gradio-client @ git+https://github.com/gradio-app/gradio@ee658cd0b5137ee656b20daa11837955cbcb418f#subdirectory=client/python"

@gradio-pr-bot
Copy link
Contributor

gradio-pr-bot commented Dec 21, 2023

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
@gradio/app patch
@gradio/client patch
gradio patch
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Fix JS Client when app is running behind a proxy

Maintainers or the PR author can modify the PR title to modify this entry.

Something isn't right?

  • Maintainers can change the version label to modify the version bump.
  • If the bot has failed to detect any changes, or if this pull request needs to update multiple packages to different versions or requires a more comprehensive changelog entry, maintainers can update the changelog file directly.

@abidlabs
Copy link
Member

🧡 thanks for fixing these long-standing issues @freddyaboulton!

@abidlabs
Copy link
Member

Does this close #4522 as well?

time: new Date()
});
post_data(
`${config.root}/run${
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why the diff is so big. But basically it's just doing this change.

@@ -26,7 +26,9 @@ test("chatinterface works with streaming functions and all buttons behave as exp
await expect(page.locator(".bot").nth(1)).toContainText("You typed: hi");

await undo_button.click();
await expect.poll(async () => page.locator(".message.bot").count()).toBe(1);
await expect
.poll(async () => page.locator(".message.bot").count(), { timeout: 5000 })
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated

@freddyaboulton
Copy link
Collaborator Author

@abidlabs Just checked and #4522 is not closed because EventSource is not available for node. Let's keep it open cc @pngwn

@freddyaboulton freddyaboulton marked this pull request as ready for review December 21, 2023 19:08
@abidlabs
Copy link
Member

so I understand, what's the connection between #4522 and EventSource?

@freddyaboulton
Copy link
Collaborator Author

It's possible that #4522 is fixed but we can't really test because we can't run the js client in node right now. It uses EventSource to read messages from the sse endpoint but the EventSource abstraction is not available in node. In the browser it should work I think.

@pngwn
Copy link
Member

pngwn commented Dec 21, 2023

Does this work for old ws/wss connections as well as http/ https? I thought config.root was just the host, not the protocol as well?

@freddyaboulton
Copy link
Collaborator Author

I don't think I changed the code for the ws connections so I think those should still work as the author of the issue mentions they don't have a problem when using 3.x.

Copy link
Collaborator

@aliabid94 aliabid94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Where was api_url being passed down from before? I couldn’t find it

@freddyaboulton
Copy link
Collaborator Author

freddyaboulton commented Dec 22, 2023

It was being computed/passed down from Index.svelte!

@freddyaboulton
Copy link
Collaborator Author

Thanks for the review @aliabid94

@freddyaboulton freddyaboulton merged commit d406855 into main Dec 22, 2023
22 of 23 checks passed
@freddyaboulton freddyaboulton deleted the 6739-fix-js-client-subdomain branch December 22, 2023 20:00
@pngwn pngwn mentioned this pull request Dec 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants