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

VS Code sends OPTIONS -- not handled by a redirect #6

Open
theflyingape opened this issue Oct 18, 2022 · 5 comments
Open

VS Code sends OPTIONS -- not handled by a redirect #6

theflyingape opened this issue Oct 18, 2022 · 5 comments

Comments

@theflyingape
Copy link

From a browser, https://server/terminal/ and https://server/terminal-vscode/ work as advertised, thank you.

But using it from VS Code does not, because we have to have our Apache server redirect /terminal-vscode/ to /terminal-vscode/index (because Route "/" is never called unless we redirect ALL "/" to CSP -- not happening). The result from VS Code is:

10.15.13.115 - - [17/Oct/2022:21:19:47 -0400] "OPTIONS /terminal-vscode/ HTTP/1.1" 302 229 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.72.2 Chrome/102.0.5005.167 Electron/19.0.17 Safari/537.36"

So a gratuitous OPTIONS is called, appropriately handled by the server, but not the client.

$ curl -X OPTIONS https://hsdev.bidmc.org/terminal-vscode/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://hsdev.bidmc.org/terminal-vscode/index">here</a>.</p>
</body></html>

image

@gjsjohnmurray
Copy link
Owner

I think the OPTIONS request is a CORS pre-flight check that occurs when this extension sends an XMLHttpRequest GET request with an Authorization header to https://hsdev.bidmc.org/terminal-vscode/ from its webview.

Instead of your Apache responding to this OPTIONS request with a 302 can it be made to return a 204 No Content with the following headers?

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Origin: {value-of-Origin-header-from request}
Vary: Origin
Access-Control-Allow-Methods: POST, GET, OPTIONS

I'm not familiar enough with Apache modules to know how/if the incoming Origin header can be returned as the value of Access-Control-Allow-Origin. Nor am I certain the above will solve your issue, as it's based on my theoretical understanding rather than testing.

I don't fully understand why you need to do that redirect of /terminal-vscode/ to /terminal-vscode/index.

Do you also have to do the equivalent for /terminal/ to make that work from a browser?

@theflyingape
Copy link
Author

@gjsjohnmurray thanks per usual timely and insightful reply.

Yes, /terminal/ and /terminal-vscode/ work from a browser as advertised. I did not know about holding ALT-click in VS Code will launch the desired URL in an external browser -- that works, so there's a viable workaround here, very cool.

I tried setting the OPTIONS response in Apache as advised, no joy launching a terminal embedded within VS Code:
10.15.13.115 - - [19/Oct/2022:09:45:10 -0400] "OPTIONS /terminal-vscode/?ns=HSCUSTOM HTTP/1.1" 204 - "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.72.2 Chrome/102.0.5005.167 Electron/19.0.17 Safari/537.36"

$ curl -D - -X OPTIONS https://hsdev.bidmc.org/terminal-vscode/
HTTP/1.1 204 No Content
Date: Wed, 19 Oct 2022 13:49:34 GMT
Server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization
Vary: Origin

We will start with the ALT-click method, thank you.

But because you asked and probably too much information posted here, the Apache service redirect is because we do not want by default for Apache to pass "everything" with an alias "/" to the CSP handler. We use a very layered httpd conf.d file layout for the variety of host needs to serve up static & dynamic content, run scripts, proxy to Node & Python services, etc.

For Caché & IRIS, we make explicit aliases to pass to their CSP handler within any VirtualHost ServerName needing it, i.e., hsdev.bidmc.org:

        Alias /api/ "${CINSTALL}/csp/"
        Alias /csp/ "${CINSTALL}/csp/"
        Alias /isc/ "${CINSTALL}/csp/"
        Alias /terminal/ "${CINSTALL}/csp/"
        Alias /terminal-vscode/ "${CINSTALL}/csp/"
        Alias /terminalsocket/ "${CINSTALL}/csp/"

The problem I see from this within %CSP.REST is that the Routes fail on a "naked" endpoint such as /terminal/ and /terminal-vscode/. This approach acts as if the endpoint result is empty "", even if I change the "/" RegExp to optional "/?":
<Route Url="/?" Method="GET" Call="Index"/>
... it does not invoke Index, thus the Apache redirects are needed:

        RewriteEngine On
        # the condition is for avoiding an infinite loop
        RewriteCond %{REQUEST_URI} !^/terminal/index.* [NC]
        RewriteRule "^/terminal/$" "/terminal/index" [QSA,R,L]
        RewriteCond %{REQUEST_URI} !^/terminal-vscode/[a-z].* [NC]
        #RewriteCond %{REQUEST_METHOD} OPTIONS
        #RewriteRule ^(.*)$ $1 [R=204,L]
        #Header always set Access-Control-Allow-Origin "*"
        #Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
        #Header always set Access-Control-Allow-Credentials "true"
        #Header always set Access-Control-Allow-Headers "Authorization"
        #Header always set Vary "Origin"
        #RewriteRule "^/terminal-vscode/$" "/terminal-vscode/index" [QSA,R,L]

Commenting out all of the /terminal-vscode/ above results in this:

$ curl -D - -X OPTIONS https://hsdev.bidmc.org/terminal-vscode/
HTTP/1.1 500 Internal Server Error
Content-type: text/html; charset=utf-8
Connection: close
Expires: Thu, 29 Oct 1998 17:04:19 GMT
Cache-Control: no-cache
Pragma: no-cache

... and commenting out /terminal/ redirect results in this:

$ curl -D - -X GET -u rhurst https://hsdev.bidmc.org/terminal/
Enter host password for user 'rhurst':
HTTP/1.1 403 Forbidden
Date: Wed, 19 Oct 2022 14:09:54 GMT
Server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k
Content-Length: 199
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body></html>

... whereas appending index works:

$ curl -D - -X GET -u rhurst https://hsdev.bidmc.org/terminal/index
Enter host password for user 'rhurst':
HTTP/1.1 200 OK
...

@gjsjohnmurray
Copy link
Owner

Something I read said that Access-Control-Allow-Origin: * isn't acceptable in CORS pre-flight response. Is there a way you can grab the value of the Origin header of the request and use that instead of *?

@theflyingape
Copy link
Author

I may be mistaken, but I don't believe we're having any CORS handling issues. OPTIONS gets consumed regardless, whether by Apache (without trail /) or by the WebTerminal.cls (required trailing /) and sameSite=none:

$ curl -D - -X OPTIONS -u rhurst 'https://hsdev.bidmc.org/terminal-vscode/'
Enter host password for user 'rhurst':
HTTP/1.1 200 OK
Date: Thu, 20 Oct 2022 14:38:13 GMT
Server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k
SET-COOKIE: CSPSESSIONID-SP-443-UP-terminal-vscode-=00f000000000jttMQ8HbCJ9tBP4xaNfm3u5HM1bETb872wToES; path=/terminal-vscode/;  secure; httpOnly; sameSite=none;
ALLOW: GET,OPTIONS
CACHE-CONTROL: no-cache
EXPIRES: Thu, 29 Oct 1998 17:04:19 GMT
PRAGMA: no-cache
SET-COOKIE: CSPWSERVERID=hA11Lxsm; path=/; httpOnly; secure;
CONTENT-LENGTH: 0
Content-Type: httpd/unix-directory

So I made this Apache service send everything "/" to CSP, so no redirects are imposed. CLI curl and incognito Browser tests all worked as expected. But from VS Code, that same OPTIONS URL is returning a 500 internal server error:

10.15.13.115 - - [20/Oct/2022:10:45:05 -0400] "GET /api/atelier/v3/HSCUSTOM/doc/WebTerminal.Router.cls HTTP/1.1" 304 - "-" "node-fetch"
10.15.13.115 - - [20/Oct/2022:10:45:08 -0400] "OPTIONS /terminal-vscode/ HTTP/1.1" 500 - "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.72.2 Chrome/102.0.5005.167 Electron/19.0.17 Safari/537.36"
10.15.13.115 - - [20/Oct/2022:10:45:55 -0400] "OPTIONS /terminal-vscode/?ns=HSCUSTOM HTTP/1.1" 500 - "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.72.2 Chrome/102.0.5005.167 Electron/19.0.17 Safari/537.36"

Changing Allow Origin to https://bidmc.org and with https://bidmc.harvard.edu made no difference:

$ curl -D - -X OPTIONS -u rhurst 'https://hsdev.bidmc.org/terminal-vscode/'
Enter host password for user 'rhurst':
HTTP/1.1 200 OK
Date: Thu, 20 Oct 2022 15:17:53 GMT
Server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k
Access-Control-Allow-Origin: https://bidmc.org
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization
Vary: Origin
SET-COOKIE: CSPSESSIONID-SP-443-UP-terminal-vscode-=000000000000qdSDewP9SPXTptOnhuw5eK65ggKFaV6GjKBYWn; path=/terminal-vscode/;  secure; httpOnly; sameSite=none;
ALLOW: GET,OPTIONS
CACHE-CONTROL: no-cache
EXPIRES: Thu, 29 Oct 1998 17:04:19 GMT
PRAGMA: no-cache
SET-COOKIE: CSPWSERVERID=hA0rcPJO; path=/; httpOnly; secure;
CONTENT-LENGTH: 0

@gjsjohnmurray
Copy link
Owner

When WebTerminal is being launched in a tab inside VS Code it is hosted by a webview. It's this architecture that makes me think that the OPTIONS requests your web server is logging when you're launching this way is a CORS preflight request.

Are you able to record more details of these requests, perhaps by using the InterSystems Web Gateway's trace facilities?

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

No branches or pull requests

2 participants