prisma / studio

🎙️ The easiest way to explore and manipulate your data in all of your Prisma projects.
https://www.prisma.io/studio
1.87k stars 47 forks source link

Configuration with reverse proxy in custom path not possible #403

Open arvindell opened 4 years ago

arvindell commented 4 years ago

Hi there. You may have seen my message on Slack. I am trying to configure Nginx to run Prisma Studio in a proxy server with custom location. For example, in myapp.com/_studio. I managed to get the relevant config working for the HTML, JS, favicon, CSS. However, the ws connection string is still not resolved properly.

I believe the problem is in this line of serverBus.js:

Screen Shot 2020-04-10 at 9 50 06

It uses window.location.host to construct the ws connection URL, but it is not taking into account the pathname that the initial request has (_studio):

Screen Shot 2020-04-10 at 9 54 04

Is there any way I can change the ws connection string myself? Any way to force it? Given that I am not in control of the Studio application, I cannot try much. Maybe it would be nice to pass an environment variable to control this behaviour. I'd suggest STUDIO_WS_HOST_CONCAT_PATHNAME or something like that.

Nginix configuration

I am leaving this if it is relevant to anyone.

location /_studio/ {
      # rewrite ^/_studio(.*) /$1 break;
      proxy_http_version 1.1;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header        Upgrade $http_upgrade;
      proxy_set_header        Connection "upgrade";
      proxy_set_header        Host https://ayzer-backend.development.positive0.com/_studio/;

      proxy_pass          http://localhost:3003/;
      proxy_read_timeout  120;
      proxy_redirect      http://localhost:3003/ https://ayzer-backend.development.positive0.com/_studio/;

    }

Environment

  1. Prisma version (prisma2 -v): prisma 2.0.0-beta.2

  2. Logs from Developer Tools Console, if any:

    
    serverBus.js:formatted:235 WebSocket connection to 'wss://ayzer-backend.development.positive0.com/' failed: Error during WebSocket handshake: Unexpected response code: 200
    connect @ serverBus.js:formatted:235
    (anonymous) @ serverBus.js:formatted:230
    482 @ serverBus.js:formatted:189
    n @ serverBus.js:formatted:11
    476 @ serverBus.js:formatted:180
    n @ serverBus.js:formatted:11
    (anonymous) @ serverBus.js:formatted:71
    (anonymous) @ serverBus.js:formatted:72
    serverBus.js:formatted:216 Socket connection interrupted
    serverBus.js:formatted:276 Websocket not open. Queueing this request: {"requestId":0,"channel":"project","action":"get","payload":{"data":null}}


Any solution or guidance would be appreciated 👍 
sdnts commented 4 years ago

Hey @alexvilchis, apologies for the delay, and thanks for the investigation! You're right that the WS URL is not configurable. Rather than an environment variable, how about I add a configuration option to Studio's server? Then I can expose it via a CLI parameter to the prisma studio command. Would that work for you?

I'm thinking of maybe reusing this config option for some other things, so STUDIO_WS_HOST_CONCAT_PATHNAME might be a bit too specific. How does something like: prisma studio --experimental --base-url="http://abc.xyz/pathname" sound to you?

Side note: I should also probably replace my rather naive approach of replacing http with ws using a regex now that the URL would be user configurable :P

sdnts commented 4 years ago

I don't know about --base-url honestly, its pretty vague, it could mean anything, I like self-documenting CLI params.

Songworks commented 3 years ago

Could the initial problem be that the mentioned n.replace(/http/, "ws") only matches http, but not https? Which results in wss://xyz being requested for the Websocket, rather than the correct ws://xyz on @alexvilchis URL? If yes, the easiest solution would probably be using /https?/ as regexp on the replace?

I had the sameish problem that the Websocket couldn't complete the handshakes, when requested through a nginx reverse proxy thingamajig. After some fiddling around with the nginx location I managed to get it work though, and now was wondering why: I'm running it locally with http:// only.

keidarcy commented 3 years ago

What's the status of this problem?I'm running into same problem.

sdnts commented 3 years ago

Hey @keidarcy and others, Studio no longer uses a Websocket connection to talk to the backend, it instead uses regular HTTP POST calls. These are made on the relative path /api. Does this problem still apply? Can someone try out the latest version and report back? What would you need to make this work if it still doesn't?

Songworks commented 3 years ago

@madebysid I should be able to try it out on a https server that has prisma-studio run through a nginx proxy. Is there a way to update prisma studio, without updating the whole of prisma v2? Probably not, but I'd rather ask first anway.

sdnts commented 3 years ago

Oh, no, since it is bundled with the prisma CLI.

If you really want though, you can use Studio's server directly (NPM package @prisma/studio-server, https://github.com/prisma/prisma/blob/master/src/packages/cli/src/Studio.ts). I'd recommend against it generaly though, things are just much simpler to configure via the CLI.

keidarcy commented 3 years ago

@madebysid I updated prisma to the latest version. I want to host prisma studio at https://xxx.xxx.com/studio with nginx proxy, then running into the relative path /api not matches. After I proxy /api to same localhost port, I get this error. Screen Shot 2021-03-29 at 20 52 20 planing to run studio to another domain with pathname /, this should work.

Songworks commented 3 years ago

Unfortunately our setup has the same issue with the relative /api. We've got prisma-studio running as hostname/prisma and a graphql endpoint already as hostname/api. While I can change the latter to anything else (ie. /graphql), the only nginx config I could get Prisma Studio to work with on prisma v2.19.0:

  # Prisma studio Frontend
  location /prisma/ {
    proxy_pass http://api:4466/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
  }

  # Prisma studio Backend, I guess?
  location ~ ^/api/? {
    proxy_pass http://api:4466;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
  }

Can't get both to run as just /api though..

@madebysid Is there any way to configure which relative path prisma studio will use? Some environment variables or anything?

Jasperhino commented 3 years ago

For me this problem also still exists, I'm running prisma studio and the backend in separate docker containers and it tries to resolve the relative /api path. Are there any updates on this?

Goaman commented 2 years ago

I'm running on the same issue.

utajum commented 2 years ago

So prisma studio has no base url variable right?

marco910 commented 2 years ago

Same issue here. Any updates on this?

kentcdodds commented 1 year ago

I would love to be able to do this for my SQLite database. I don't have any nice way to inspect my data running on a remote server so I'd love to have an authenticated proxy for prisma studio.

kentcdodds commented 1 year ago

I've got this working with a few simple changes. I'm hosting my prisma studio proxied behind https://my-site.com/prisma-studio/. Here are the changes I needed to make:

  1. For some reason the ./ in the assets linked to from the index.html document were ignoring the relativeness of ./ so I had to change those to /prisma-studio/. I'm not sure why that didn't work as expected...
  2. I updated prisma/build/public/http/databrowser.js, prisma/build/public/http/splash.js, and prisma/build/public/assets/index.js to do this: ${window.location.origin}${window.location.pathname}${window.location.pathname.endsWith('/') ? '' : '/'}api instead of: ${window.location.origin}/api

And that was enough of the changes in prisma's code to make it proxyable. I'm not sure why that first thing had to happen because I believe ./ for assets linked in an HTML document should be resolved relative to the URL where the HTML document appears 🤷‍♂️ But for part 2 that was pretty straightforward.

andrewbrey commented 1 year ago

@kentcdodds - for a toy app I made (https://github.com/andrewbrey/wael) that is also sqlite + prisma + remix, I accomplished the same kind of proxy for runtime access to prisma studio with minimal changes needed to the prisma source files. Take a look at the server.js here: https://github.com/andrewbrey/wael/blob/05fda8ee20aa436e449c5e8a3a4daadb7023aa28/server.js#L25:L49

Note in particular the use of the html base attribute that is just about the only required modification to prisma sources to allow proxying to work just peachy :smile:

fritx commented 11 months ago
  # Prisma studio Backend, I guess?
  location ~ ^/api/? {
    proxy_pass http://api:4466;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
  }

Can't get both to run as just /api though..

@madebysid Is there any way to configure which relative path prisma studio will use? Some environment variables or anything?

Still an issue. But I finally got it to work by:

# prisma studio
# Configuration with reverse proxy in custom path not possible #403
# https://github.com/prisma/studio/issues/403
location = /data {
  rewrite ^(.*[^/])$ $1/ redirect;
}
location /data {
  rewrite /data/(.*) /$1  break;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_pass http://127.0.0.1:5555;
  auth_basic "Restricted Content";
  auth_basic_user_file /.../.htpasswd;
}
location = /api {
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_pass http://127.0.0.1:5555;
  auth_basic "Restricted Content";
  auth_basic_user_file /.../.htpasswd;
}

Thanks to that prisma-studio using exact /api. I use location = to match it while I have /api/xxx for other services as well. @Songworks

macrozone commented 9 months ago

I've got this working with a few simple changes. I'm hosting my prisma studio proxied behind https://my-site.com/prisma-studio/. Here are the changes I needed to make:

  1. For some reason the ./ in the assets linked to from the index.html document were ignoring the relativeness of ./ so I had to change those to /prisma-studio/. I'm not sure why that didn't work as expected...
  2. I updated prisma/build/public/http/databrowser.js, prisma/build/public/http/splash.js, and prisma/build/public/assets/index.js to do this: ${window.location.origin}${window.location.pathname}${window.location.pathname.endsWith('/') ? '' : '/'}api instead of: ${window.location.origin}/api

And that was enough of the changes in prisma's code to make it proxyable. I'm not sure why that first thing had to happen because I believe ./ for assets linked in an HTML document should be resolved relative to the URL where the HTML document appears 🤷‍♂️ But for part 2 that was pretty straightforward.

is there some update from the prisma team to have that?

marcovc commented 7 months ago

Just confirming this still works in 2024 (although it seems there is no index.html anymore).