Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gzupanda
code-server
提交
6cebfa46
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,发现更多精彩内容 >>
未验证
提交
6cebfa46
编写于
2月 05, 2020
作者:
A
Asher
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Generalize initial app logic
上级
205775ac
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
78 addition
and
57 deletion
+78
-57
src/browser/api.ts
src/browser/api.ts
+10
-6
src/browser/app.tsx
src/browser/app.tsx
+11
-12
src/browser/components/modal.tsx
src/browser/components/modal.tsx
+2
-7
src/browser/pages/home.tsx
src/browser/pages/home.tsx
+4
-2
src/browser/pages/login.tsx
src/browser/pages/login.tsx
+18
-4
src/common/api.ts
src/common/api.ts
+5
-1
src/node/api/server.ts
src/node/api/server.ts
+10
-7
src/node/app/server.tsx
src/node/app/server.tsx
+17
-15
src/node/http.ts
src/node/http.ts
+1
-3
未找到文件。
src/browser/api.ts
浏览文件 @
6cebfa46
import
{
getBasepath
}
from
"
hookrouter
"
import
{
Application
,
ApplicationsResponse
,
CreateSessionResponse
,
FilesResponse
,
RecentResponse
}
from
"
../common/api
"
import
{
Application
,
ApplicationsResponse
,
CreateSessionResponse
,
FilesResponse
,
LoginResponse
,
RecentResponse
,
}
from
"
../common/api
"
import
{
ApiEndpoint
,
HttpCode
,
HttpError
}
from
"
../common/http
"
export
interface
AuthBody
{
...
...
@@ -33,7 +40,7 @@ const tryRequest = async (endpoint: string, options?: RequestInit): Promise<Resp
/**
* Try authenticating.
*/
export
const
authenticate
=
async
(
body
?:
AuthBody
):
Promise
<
void
>
=>
{
export
const
authenticate
=
async
(
body
?:
AuthBody
):
Promise
<
LoginResponse
>
=>
{
const
response
=
await
tryRequest
(
ApiEndpoint
.
login
,
{
method
:
"
POST
"
,
body
:
JSON
.
stringify
({
...
body
,
basePath
:
getBasepath
()
}),
...
...
@@ -41,10 +48,7 @@ export const authenticate = async (body?: AuthBody): Promise<void> => {
"
Content-Type
"
:
"
application/x-www-form-urlencoded; charset=utf-8
"
,
},
})
const
json
=
await
response
.
json
()
if
(
json
&&
json
.
success
)
{
setAuthed
(
true
)
}
return
response
.
json
()
}
export
const
getFiles
=
async
():
Promise
<
FilesResponse
>
=>
{
...
...
src/browser/app.tsx
浏览文件 @
6cebfa46
...
...
@@ -10,34 +10,33 @@ export interface AppProps {
options
:
Options
}
interface
RedirectedApplication
extends
Application
{
redirected
?:
boolean
}
const
origin
=
typeof
window
!==
"
undefined
"
?
window
.
location
.
origin
+
window
.
location
.
pathname
:
undefined
const
App
:
React
.
FunctionComponent
<
AppProps
>
=
(
props
)
=>
{
const
[
authed
,
setAuthed
]
=
React
.
useState
<
boolean
>
(
props
.
options
.
authed
)
const
[
app
,
setApp
]
=
React
.
useState
<
Application
|
undefined
>
(
props
.
options
.
app
)
const
[
app
,
setApp
]
=
React
.
useState
<
Redirected
Application
|
undefined
>
(
props
.
options
.
app
)
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
|
Error
|
string
>
()
if
(
typeof
window
!==
"
undefined
"
)
{
const
url
=
new
URL
(
window
.
location
.
origin
+
window
.
location
.
pathname
+
props
.
options
.
basePath
)
const
url
=
new
URL
(
origin
+
props
.
options
.
basePath
)
setBasepath
(
normalize
(
url
.
pathname
))
// eslint-disable-next-line @typescript-eslint/no-explicit-any
;(
window
as
any
).
setAuthed
=
(
a
:
boolean
):
void
=>
{
if
(
authed
!==
a
)
{
setAuthed
(
a
)
// TEMP: Remove when no longer auto-loading VS Code.
if
(
a
&&
!
app
)
{
setApp
({
name
:
"
VS Code
"
,
path
:
"
/
"
,
embedPath
:
"
/vscode-embed
"
,
})
}
}
}
}
React
.
useEffect
(()
=>
{
if
(
app
&&
!
isExecutableApplication
(
app
))
{
if
(
app
&&
!
isExecutableApplication
(
app
)
&&
!
app
.
redirected
)
{
navigate
(
normalize
(
`
${
getBasepath
()}
/
${
app
.
path
}
/`
,
true
))
setApp
({
...
app
,
redirected
:
true
})
}
},
[
app
])
...
...
@@ -51,7 +50,7 @@ const App: React.FunctionComponent<AppProps> = (props) => {
undefined
)
}
<
Modal
app
=
{
app
}
setApp
=
{
setApp
}
authed
=
{
authed
}
error
=
{
error
}
setError
=
{
setError
}
/>
{
authed
&&
app
&&
app
.
embedPath
?
(
{
authed
&&
app
&&
app
.
embedPath
&&
app
.
redirected
?
(
<
iframe
id
=
"iframe"
src
=
{
normalize
(
`./
${
app
.
embedPath
}
/`
,
true
)
}
></
iframe
>
)
:
(
undefined
...
...
src/browser/components/modal.tsx
浏览文件 @
6cebfa46
...
...
@@ -22,7 +22,6 @@ export interface ModalProps {
enum
Section
{
Browse
,
Home
,
Login
,
Open
,
Recent
,
}
...
...
@@ -103,7 +102,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
const
content
=
():
React
.
ReactElement
=>
{
if
(
!
props
.
authed
)
{
return
<
Login
/>
return
<
Login
setApp
=
{
setApp
}
/>
}
switch
(
section
)
{
case
Section
.
Recent
:
...
...
@@ -112,8 +111,6 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
return
<
Home
app
=
{
props
.
app
}
/>
case
Section
.
Browse
:
return
<
Browse
/>
case
Section
.
Login
:
return
<
Login
/>
case
Section
.
Open
:
return
<
Open
app
=
{
props
.
app
}
setApp
=
{
setApp
}
/>
default
:
...
...
@@ -140,9 +137,7 @@ export const Modal: React.FunctionComponent<ModalProps> = (props) => {
</
button
>
</>
)
:
(
<
button
className
=
"link"
onClick
=
{
():
void
=>
setSection
(
Section
.
Login
)
}
>
Login
</
button
>
undefined
)
}
</
nav
>
<
div
className
=
"footer"
>
...
...
src/browser/pages/home.tsx
浏览文件 @
6cebfa46
import
*
as
React
from
"
react
"
import
{
Application
}
from
"
../../common/api
"
import
{
authenticate
}
from
"
../api
"
import
{
authenticate
,
setAuthed
}
from
"
../api
"
export
interface
HomeProps
{
app
?:
Application
...
...
@@ -8,7 +8,9 @@ export interface HomeProps {
export
const
Home
:
React
.
FunctionComponent
<
HomeProps
>
=
(
props
)
=>
{
React
.
useEffect
(()
=>
{
authenticate
().
catch
(()
=>
undefined
)
authenticate
()
.
then
(()
=>
setAuthed
(
true
))
.
catch
(()
=>
undefined
)
},
[])
return
(
...
...
src/browser/pages/login.tsx
浏览文件 @
6cebfa46
import
*
as
React
from
"
react
"
import
{
Application
}
from
"
../../common/api
"
import
{
HttpError
}
from
"
../../common/http
"
import
{
authenticate
}
from
"
../api
"
import
{
authenticate
,
setAuthed
}
from
"
../api
"
import
{
FieldError
}
from
"
../components/error
"
export
interface
LoginProps
{
setApp
(
app
:
Application
):
void
}
/**
* Login page. Will redirect on success.
*/
export
const
Login
:
React
.
FunctionComponent
=
(
)
=>
{
export
const
Login
:
React
.
FunctionComponent
<
LoginProps
>
=
(
props
)
=>
{
const
[
password
,
setPassword
]
=
React
.
useState
<
string
>
(
""
)
const
[
error
,
setError
]
=
React
.
useState
<
HttpError
>
()
async
function
handleSubmit
(
event
:
React
.
FormEvent
<
HTMLFormElement
>
):
Promise
<
void
>
{
event
.
preventDefault
()
authenticate
({
password
}).
catch
(
setError
)
authenticate
({
password
})
.
then
((
response
)
=>
{
if
(
response
.
app
)
{
props
.
setApp
(
response
.
app
)
}
setAuthed
(
true
)
})
.
catch
(
setError
)
}
React
.
useEffect
(()
=>
{
authenticate
().
catch
(()
=>
undefined
)
authenticate
()
.
then
(()
=>
setAuthed
(
true
))
.
catch
(()
=>
undefined
)
},
[])
return
(
...
...
src/common/api.ts
浏览文件 @
6cebfa46
...
...
@@ -23,11 +23,15 @@ export enum SessionError {
}
export
interface
LoginRequest
{
password
:
string
basePath
:
string
password
:
string
}
export
interface
LoginResponse
{
/**
* An application to load immediately after logging in.
*/
app
?:
Application
success
:
boolean
}
...
...
src/node/api/server.ts
浏览文件 @
6cebfa46
...
...
@@ -3,6 +3,7 @@ import * as http from "http"
import
*
as
net
from
"
net
"
import
*
as
ws
from
"
ws
"
import
{
Application
,
ApplicationsResponse
,
ClientMessage
,
FilesResponse
,
...
...
@@ -15,6 +16,12 @@ import { normalize } from "../../common/util"
import
{
HttpProvider
,
HttpProviderOptions
,
HttpResponse
,
HttpServer
,
Route
}
from
"
../http
"
import
{
hash
}
from
"
../util
"
export
const
Vscode
:
Application
=
{
name
:
"
VS Code
"
,
path
:
"
/
"
,
embedPath
:
"
./vscode-embed
"
,
}
/**
* API HTTP provider.
*/
...
...
@@ -104,6 +111,8 @@ export class ApiHttpProvider extends HttpProvider {
return
{
content
:
{
success
:
true
,
// TEMP: Auto-load VS Code.
app
:
Vscode
,
},
cookie
:
typeof
password
===
"
string
"
...
...
@@ -149,13 +158,7 @@ export class ApiHttpProvider extends HttpProvider {
private
async
applications
():
Promise
<
HttpResponse
<
ApplicationsResponse
>>
{
return
{
content
:
{
applications
:
[
{
name
:
"
VS Code
"
,
path
:
"
/vscode
"
,
embedPath
:
"
/vscode-embed
"
,
},
],
applications
:
[
Vscode
],
},
}
}
...
...
src/node/app/server.tsx
浏览文件 @
6cebfa46
...
...
@@ -5,6 +5,7 @@ import * as ReactDOMServer from "react-dom/server"
import
App
from
"
../../browser/app
"
import
{
HttpCode
,
HttpError
}
from
"
../../common/http
"
import
{
Options
}
from
"
../../common/util
"
import
{
Vscode
}
from
"
../api/server
"
import
{
HttpProvider
,
HttpResponse
,
Route
}
from
"
../http
"
/**
...
...
@@ -21,39 +22,40 @@ export class MainHttpProvider extends HttpProvider {
return
response
}
case
"
/vscode
"
:
case
"
/
"
:
{
if
(
route
.
requestPath
!==
"
/index.html
"
)
{
throw
new
HttpError
(
"
Not found
"
,
HttpCode
.
NotFound
)
}
const
options
:
Options
=
{
authed
:
!!
this
.
authenticated
(
request
),
basePath
:
this
.
base
(
route
),
logLevel
:
logger
.
level
,
}
if
(
options
.
authed
)
{
// TEMP: Auto-load VS Code for now. In future versions we'll need to check
// the URL for the appropriate application to load, if any.
options
.
app
=
{
name
:
"
VS Code
"
,
path
:
"
/
"
,
embedPath
:
"
/vscode-embed
"
,
}
// TODO: Load other apps based on the URL as well.
if
(
route
.
base
===
Vscode
.
path
&&
options
.
authed
)
{
options
.
app
=
Vscode
}
const
response
=
await
this
.
getUtf8Resource
(
this
.
rootPath
,
"
src/browser/index.html
"
)
response
.
content
=
response
.
content
.
replace
(
/{{COMMIT}}/g
,
this
.
options
.
commit
)
.
replace
(
/{{BASE}}/g
,
this
.
base
(
route
))
.
replace
(
/"{{OPTIONS}}"/g
,
`'
${
JSON
.
stringify
(
options
)}
'`
)
.
replace
(
/{{COMPONENT}}/g
,
ReactDOMServer
.
renderToString
(<
App
options
=
{
options
}
/>))
return
response
return
this
.
getRoot
(
route
,
options
)
}
}
return
undefined
}
public
async
getRoot
(
route
:
Route
,
options
:
Options
):
Promise
<
HttpResponse
>
{
const
response
=
await
this
.
getUtf8Resource
(
this
.
rootPath
,
"
src/browser/index.html
"
)
response
.
content
=
response
.
content
.
replace
(
/{{COMMIT}}/g
,
this
.
options
.
commit
)
.
replace
(
/{{BASE}}/g
,
this
.
base
(
route
))
.
replace
(
/"{{OPTIONS}}"/g
,
`'
${
JSON
.
stringify
(
options
)}
'`
)
.
replace
(
/{{COMPONENT}}/g
,
ReactDOMServer
.
renderToString
(<
App
options
=
{
options
}
/>))
return
response
}
public
async
handleWebSocket
():
Promise
<
undefined
>
{
return
undefined
}
...
...
src/node/http.ts
浏览文件 @
6cebfa46
...
...
@@ -116,7 +116,6 @@ interface ProviderRoute extends Route {
}
export
interface
HttpProviderOptions
{
readonly
base
:
string
readonly
auth
:
AuthType
readonly
password
?:
string
readonly
commit
:
string
...
...
@@ -154,7 +153,7 @@ export abstract class HttpProvider {
* Get the base relative to the provided route.
*/
public
base
(
route
:
Route
):
string
{
const
depth
=
route
.
fullPath
?
(
route
.
fullPath
.
match
(
/
\/
/g
)
||
[]).
length
:
1
const
depth
=
((
route
.
fullPath
+
"
/
"
).
match
(
/
\/
/g
)
||
[]).
length
return
normalize
(
"
./
"
+
(
depth
>
1
?
"
../
"
.
repeat
(
depth
-
1
)
:
""
))
}
...
...
@@ -404,7 +403,6 @@ export class HttpServer {
new
provider
(
{
auth
:
this
.
options
.
auth
||
AuthType
.
None
,
base
:
endpoint
,
commit
:
this
.
options
.
commit
,
password
:
this
.
options
.
password
,
},
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录