Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gzupanda
code-server
提交
cf30b536
C
code-server
项目概览
gzupanda
/
code-server
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
code-server
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
cf30b536
编写于
2月 05, 2021
作者:
A
Anmol Sethi
提交者:
GitHub
2月 05, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #2674 from nhooyr/absproxy
Add /absproxy to remove --proxy-path-passthrough
上级
4bace1ae
05a0f213
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
73 addition
and
46 deletion
+73
-46
docs/FAQ.md
docs/FAQ.md
+16
-12
src/node/cli.ts
src/node/cli.ts
+0
-5
src/node/proxy.ts
src/node/proxy.ts
+1
-2
src/node/routes/index.ts
src/node/routes/index.ts
+19
-2
src/node/routes/pathProxy.ts
src/node/routes/pathProxy.ts
+28
-18
test/proxy.test.ts
test/proxy.test.ts
+9
-7
未找到文件。
docs/FAQ.md
浏览文件 @
cf30b536
...
...
@@ -16,6 +16,7 @@
-
[
Sub-paths
](
#sub-paths
)
-
[
Sub-domains
](
#sub-domains
)
-
[
Why does the code-server proxy strip `/proxy/<port>` from the request path?
](
#why-does-the-code-server-proxy-strip-proxyport-from-the-request-path
)
-
[
Proxying to Create React App
](
#proxying-to-create-react-app
)
-
[
Multi-tenancy
](
#multi-tenancy
)
-
[
Docker in code-server container?
](
#docker-in-code-server-container
)
-
[
How can I disable telemetry?
](
#how-can-i-disable-telemetry
)
...
...
@@ -226,25 +227,28 @@ However many people prefer the cleaner aesthetic of no trailing slashes. This co
to the base path as you cannot use relative redirects correctly anymore. See the above
link.
For users who are ok with this tradeoff,
pass
`--proxy-path-passthrough`
to code-server
and the path will be passed as is.
For users who are ok with this tradeoff,
use
`/absproxy`
instead and the path will be
passed as is. e.g.
`/absproxy/3000/my-app-path`
This is particularly a problem with the
`start`
script in create-react-app. See
### Proxying to Create React App
You must use
`/absproxy/<port>`
with create-react-app.
See
[
#2565
](
https://github.com/cdr/code-server/issues/2565
)
and
[
#2222
](
https://github.com/cdr/code-server/issues/2222
)
. You will need to inform
create-react-app of the path at which you are serving via
`
homepage`
field in your
`package.json`
. e.g. you'd add the following for the default CRA port:
create-react-app of the path at which you are serving via
`
$PUBLIC_URL`
and webpack
via
`$WDS_SOCKET_PATH`
.
```
json
"homepage"
:
"/proxy/3000"
,
e.g.
```
sh
PUBLIC_URL
=
/absproxy/3000
\
WDS_SOCKET_PATH
=
$PUBLIC_URL
/sockjs-node
\
BROWSER
=
none yarn start
```
Then visit
`https://my-code-server-address.io/proxy/3000`
to see your app exposed through
Then visit
`https://my-code-server-address.io/
abs
proxy/3000`
to see your app exposed through
code-server!
Unfortunately
`webpack-dev-server`
's websocket connections will not go through as it
always uses
`/sockjs-node`
. So hot reloading will not work until the
`create-react-app`
team fix this bug.
Highly recommend using the subdomain approach instead to avoid this class of issue.
## Multi-tenancy
...
...
src/node/cli.ts
浏览文件 @
cf30b536
...
...
@@ -50,7 +50,6 @@ export interface Args extends VsArgs {
"
show-versions
"
?:
boolean
"
uninstall-extension
"
?:
string
[]
"
proxy-domain
"
?:
string
[]
"
proxy-path-passthrough
"
?:
boolean
locale
?:
string
_
:
string
[]
"
reuse-window
"
?:
boolean
...
...
@@ -173,10 +172,6 @@ const options: Options<Required<Args>> = {
"
uninstall-extension
"
:
{
type
:
"
string[]
"
,
description
:
"
Uninstall a VS Code extension by id.
"
},
"
show-versions
"
:
{
type
:
"
boolean
"
,
description
:
"
Show VS Code extension versions.
"
},
"
proxy-domain
"
:
{
type
:
"
string[]
"
,
description
:
"
Domain used for proxying ports.
"
},
"
proxy-path-passthrough
"
:
{
type
:
"
boolean
"
,
description
:
"
Whether the path proxy should leave the /proxy/<port> in the request path when proxying.
"
,
},
"
ignore-last-opened
"
:
{
type
:
"
boolean
"
,
short
:
"
e
"
,
...
...
src/node/proxy.ts
浏览文件 @
cf30b536
...
...
@@ -9,8 +9,7 @@ proxy.on("error", (error, _, res) => {
})
// Intercept the response to rewrite absolute redirects against the base path.
// Is disabled when the request has no base path which means --proxy-path-passthrough has
// been enabled.
// Is disabled when the request has no base path which means /absproxy is in use.
proxy
.
on
(
"
proxyRes
"
,
(
res
,
req
)
=>
{
if
(
res
.
headers
.
location
&&
res
.
headers
.
location
.
startsWith
(
"
/
"
)
&&
(
req
as
any
).
base
)
{
res
.
headers
.
location
=
(
req
as
any
).
base
+
res
.
headers
.
location
...
...
src/node/routes/index.ts
浏览文件 @
cf30b536
...
...
@@ -103,8 +103,25 @@ export const register = async (
app
.
use
(
"
/
"
,
domainProxy
.
router
)
wsApp
.
use
(
"
/
"
,
domainProxy
.
wsRouter
.
router
)
app
.
use
(
"
/proxy
"
,
proxy
.
router
)
wsApp
.
use
(
"
/proxy
"
,
proxy
.
wsRouter
.
router
)
app
.
all
(
"
/proxy/(:port)(/*)?
"
,
(
req
,
res
)
=>
{
proxy
.
proxy
(
req
,
res
)
})
wsApp
.
get
(
"
/proxy/(:port)(/*)?
"
,
(
req
,
res
)
=>
{
proxy
.
wsProxy
(
req
as
WebsocketRequest
)
})
// These two routes pass through the path directly.
// So the proxied app must be aware it is running
// under /absproxy/<someport>/
app
.
all
(
"
/absproxy/(:port)(/*)?
"
,
(
req
,
res
)
=>
{
proxy
.
proxy
(
req
,
res
,
{
passthroughPath
:
true
,
})
})
wsApp
.
get
(
"
/absproxy/(:port)(/*)?
"
,
(
req
,
res
)
=>
{
proxy
.
wsProxy
(
req
as
WebsocketRequest
,
{
passthroughPath
:
true
,
})
})
app
.
use
(
bodyParser
.
json
())
app
.
use
(
bodyParser
.
urlencoded
({
extended
:
true
}))
...
...
src/node/routes/pathProxy.ts
浏览文件 @
cf30b536
import
{
Request
,
Router
}
from
"
express
"
import
{
Request
,
Response
}
from
"
express
"
import
*
as
path
from
"
path
"
import
qs
from
"
qs
"
import
{
HttpCode
,
HttpError
}
from
"
../../common/http
"
import
{
normalize
}
from
"
../../common/util
"
import
{
authenticated
,
ensureAuthenticated
,
redirect
}
from
"
../http
"
import
{
proxy
}
from
"
../proxy
"
import
{
Router
as
WsRouter
}
from
"
../wsRouter
"
import
{
proxy
as
_proxy
}
from
"
../proxy
"
import
{
WebsocketRequest
}
from
"
../wsRouter
"
export
const
router
=
Router
()
const
getProxyTarget
=
(
req
:
Request
,
passthroughPath
:
boolean
):
string
=>
{
const
getProxyTarget
=
(
req
:
Request
,
passthroughPath
?:
boolean
):
string
=>
{
if
(
passthroughPath
)
{
return
`http://0.0.0.0:
${
req
.
params
.
port
}
/
${
req
.
originalUrl
}
`
}
...
...
@@ -16,7 +15,13 @@ const getProxyTarget = (req: Request, passthroughPath: boolean): string => {
return
`http://0.0.0.0:
${
req
.
params
.
port
}
/
${
req
.
params
[
0
]
||
""
}${
query
?
`?
${
query
}
`
:
""
}
`
}
router
.
all
(
"
/(:port)(/*)?
"
,
(
req
,
res
)
=>
{
export
function
proxy
(
req
:
Request
,
res
:
Response
,
opts
?:
{
passthroughPath
?:
boolean
},
):
void
{
if
(
!
authenticated
(
req
))
{
// If visiting the root (/:port only) redirect to the login page.
if
(
!
req
.
params
[
0
]
||
req
.
params
[
0
]
===
"
/
"
)
{
...
...
@@ -28,22 +33,27 @@ router.all("/(:port)(/*)?", (req, res) => {
throw
new
HttpError
(
"
Unauthorized
"
,
HttpCode
.
Unauthorized
)
}
if
(
!
req
.
args
[
"
proxy-path-passthrough
"
]
)
{
if
(
!
opts
?.
passthroughPath
)
{
// Absolute redirects need to be based on the subpath when rewriting.
;(
req
as
any
).
base
=
`
${
req
.
baseUrl
}
/
${
req
.
params
.
port
}
`
// See proxy.ts.
;(
req
as
any
).
base
=
req
.
path
.
split
(
path
.
sep
).
slice
(
0
,
3
).
join
(
path
.
sep
)
}
proxy
.
web
(
req
,
res
,
{
_
proxy
.
web
(
req
,
res
,
{
ignorePath
:
true
,
target
:
getProxyTarget
(
req
,
req
.
args
[
"
proxy-path-passthrough
"
]
||
false
),
target
:
getProxyTarget
(
req
,
opts
?.
passthroughPath
),
})
})
export
const
wsRouter
=
WsRouter
()
}
wsRouter
.
ws
(
"
/(:port)(/*)?
"
,
ensureAuthenticated
,
(
req
)
=>
{
proxy
.
ws
(
req
,
req
.
ws
,
req
.
head
,
{
export
function
wsProxy
(
req
:
WebsocketRequest
,
opts
?:
{
passthroughPath
?:
boolean
},
):
void
{
ensureAuthenticated
(
req
)
_proxy
.
ws
(
req
,
req
.
ws
,
req
.
head
,
{
ignorePath
:
true
,
target
:
getProxyTarget
(
req
,
req
.
args
[
"
proxy-path-passthrough
"
]
||
false
),
target
:
getProxyTarget
(
req
,
opts
?.
passthroughPath
),
})
}
)
}
test/proxy.test.ts
浏览文件 @
cf30b536
...
...
@@ -7,6 +7,7 @@ describe("proxy", () => {
const
nhooyrDevServer
=
new
httpserver
.
HttpServer
()
let
codeServer
:
httpserver
.
HttpServer
|
undefined
let
proxyPath
:
string
let
absProxyPath
:
string
let
e
:
express
.
Express
beforeAll
(
async
()
=>
{
...
...
@@ -14,6 +15,7 @@ describe("proxy", () => {
e
(
req
,
res
)
})
proxyPath
=
`/proxy/
${
nhooyrDevServer
.
port
()}
/wsup`
absProxyPath
=
proxyPath
.
replace
(
"
/proxy/
"
,
"
/absproxy/
"
)
})
afterAll
(
async
()
=>
{
...
...
@@ -43,11 +45,11 @@ describe("proxy", () => {
})
it
(
"
should not rewrite the base path
"
,
async
()
=>
{
e
.
get
(
p
roxyPath
,
(
req
,
res
)
=>
{
e
.
get
(
absP
roxyPath
,
(
req
,
res
)
=>
{
res
.
json
(
"
joe is the best
"
)
})
;[,
,
codeServer
]
=
await
integration
.
setup
([
"
--auth=none
"
,
"
--proxy-path-passthrough=true
"
],
""
)
const
resp
=
await
codeServer
.
fetch
(
p
roxyPath
)
;[,
,
codeServer
]
=
await
integration
.
setup
([
"
--auth=none
"
],
""
)
const
resp
=
await
codeServer
.
fetch
(
absP
roxyPath
)
expect
(
resp
.
status
).
toBe
(
200
)
const
json
=
await
resp
.
json
()
expect
(
json
).
toBe
(
"
joe is the best
"
)
...
...
@@ -69,15 +71,15 @@ describe("proxy", () => {
})
it
(
"
should not rewrite redirects
"
,
async
()
=>
{
const
finalePath
=
p
roxyPath
.
replace
(
"
/wsup
"
,
"
/finale
"
)
e
.
post
(
p
roxyPath
,
(
req
,
res
)
=>
{
const
finalePath
=
absP
roxyPath
.
replace
(
"
/wsup
"
,
"
/finale
"
)
e
.
post
(
absP
roxyPath
,
(
req
,
res
)
=>
{
res
.
redirect
(
307
,
finalePath
)
})
e
.
post
(
finalePath
,
(
req
,
res
)
=>
{
res
.
json
(
"
redirect success
"
)
})
;[,
,
codeServer
]
=
await
integration
.
setup
([
"
--auth=none
"
,
"
--proxy-path-passthrough=true
"
],
""
)
const
resp
=
await
codeServer
.
fetch
(
p
roxyPath
,
{
;[,
,
codeServer
]
=
await
integration
.
setup
([
"
--auth=none
"
],
""
)
const
resp
=
await
codeServer
.
fetch
(
absP
roxyPath
,
{
method
:
"
POST
"
,
})
expect
(
resp
.
status
).
toBe
(
200
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录