FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
code-server/src/node/app.ts at asher/enable-webkit · coder/code-server · GitHub
coder
code-server
Repository navigation
Code
Issues
144
(144)
Pull requests
14
(14)
Discussions
Actions
Projects
Security and quality
1
(1)
Insights
Expand file tree
Breadcrumbs
code-server
/
src
/
node
/
app.ts
Copy path
More file actions
More file actions
Latest commit
History
History
History
141 lines (122 loc) · 4.49 KB
Breadcrumbs
code-server
/
src
/
node
/
app.ts
Copy path
File metadata and controls
141 lines (122 loc) · 4.49 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import
{
logger
}
from
"@coder/logger"
import
compression
from
"compression"
import
express
,
{
Express
}
from
"express"
import
{
promises
as
fs
}
from
"fs"
import
http
from
"http"
import
*
as
httpolyglot
from
"httpolyglot"
import
{
Disposable
}
from
"../common/emitter"
import
*
as
util
from
"../common/util"
import
{
DefaultedArgs
}
from
"./cli"
import
{
disposer
}
from
"./http"
import
{
isNodeJSErrnoException
}
from
"./util"
import
{
EditorSessionManager
,
makeEditorSessionManagerServer
}
from
"./vscodeSocket"
import
{
handleUpgrade
}
from
"./wsRouter"
type
SocketOptions
=
{
socket
:
string
;
"socket-mode"
?:
string
}
type
FdOptions
=
{
"socket-fd"
:
number
}
type
ListenOptions
=
DefaultedArgs
|
SocketOptions
|
FdOptions
export
interface
App
extends
Disposable
{
/** Handles regular HTTP requests. */
router
:
Express
/** Handles websocket requests. */
wsRouter
:
Express
/** The underlying HTTP server. */
server
:
http
.
Server
/** Handles requests to the editor session management API. */
editorSessionManagerServer
:
http
.
Server
}
const
isSocketOpts
=
(
opts
:
ListenOptions
)
:
opts
is
SocketOptions
=>
{
return
!
!
(
opts
as
SocketOptions
)
.
socket
||
!
(
opts
as
DefaultedArgs
)
.
host
}
export
const
isFdOpts
=
(
opts
:
ListenOptions
)
:
opts
is
FdOptions
=>
{
return
typeof
(
opts
as
FdOptions
)
[
"socket-fd"
]
===
"number"
}
export
const
listen
=
async
(
server
:
http
.
Server
,
opts
:
ListenOptions
)
=>
{
if
(
!
isFdOpts
(
opts
)
&&
isSocketOpts
(
opts
)
)
{
try
{
await
fs
.
unlink
(
opts
.
socket
)
}
catch
(
error
:
any
)
{
handleArgsSocketCatchError
(
error
)
}
}
await
new
Promise
<
void
>
(
async
(
resolve
,
reject
)
=>
{
server
.
on
(
"error"
,
reject
)
const
onListen
=
(
)
=>
{
// Promise resolved earlier so this is an unrelated error.
server
.
off
(
"error"
,
reject
)
server
.
on
(
"error"
,
(
err
)
=>
util
.
logError
(
logger
,
"http server error"
,
err
)
)
resolve
(
)
}
if
(
isFdOpts
(
opts
)
)
{
server
.
listen
(
{
fd
:
opts
[
"socket-fd"
]
}
,
onListen
)
}
else
if
(
isSocketOpts
(
opts
)
)
{
server
.
listen
(
opts
.
socket
,
onListen
)
}
else
{
// [] is the correct format when using :: but Node errors with them.
server
.
listen
(
opts
.
port
,
opts
.
host
.
replace
(
/
^
\[
|
\]
$
/
g
,
""
)
,
onListen
)
}
}
)
// NOTE
@jsjoeio
: we need to chmod after the server is finished
// listening. Otherwise, the socket may not have been created yet.
if
(
!
isFdOpts
(
opts
)
&&
isSocketOpts
(
opts
)
)
{
if
(
opts
[
"socket-mode"
]
)
{
await
fs
.
chmod
(
opts
.
socket
,
opts
[
"socket-mode"
]
)
}
}
}
/**
* Create an Express app and an HTTP/S server to serve it.
*/
export
const
createApp
=
async
(
args
:
DefaultedArgs
)
:
Promise
<
App
>
=>
{
const
router
=
express
(
)
router
.
use
(
compression
(
)
)
const
server
=
args
.
cert
?
httpolyglot
.
createServer
(
{
cert
:
args
.
cert
&&
(
await
fs
.
readFile
(
args
.
cert
.
value
)
)
,
key
:
args
[
"cert-key"
]
&&
(
await
fs
.
readFile
(
args
[
"cert-key"
]
)
)
,
}
,
router
,
)
:
http
.
createServer
(
router
)
const
disposeServer
=
disposer
(
server
)
await
listen
(
server
,
args
)
const
wsRouter
=
express
(
)
handleUpgrade
(
wsRouter
,
server
)
const
editorSessionManager
=
new
EditorSessionManager
(
)
const
editorSessionManagerServer
=
await
makeEditorSessionManagerServer
(
args
[
"session-socket"
]
,
editorSessionManager
)
const
disposeEditorSessionManagerServer
=
disposer
(
editorSessionManagerServer
)
const
dispose
=
async
(
)
=>
{
await
Promise
.
all
(
[
disposeServer
(
)
,
disposeEditorSessionManagerServer
(
)
]
)
}
return
{
router
,
wsRouter
,
server
,
dispose
,
editorSessionManagerServer
}
}
/**
* Get the address of a server as a string (protocol *is* included) while
* ensuring there is one (will throw if there isn't).
*
* The address might be a URL or it might be a pipe or socket path.
*/
export
const
ensureAddress
=
(
server
:
http
.
Server
,
protocol
:
string
)
:
URL
|
string
=>
{
const
addr
=
server
.
address
(
)
if
(
!
addr
)
{
throw
new
Error
(
"Server has no address"
)
}
if
(
typeof
addr
!==
"string"
)
{
const
host
=
addr
.
family
===
"IPv6"
?
`[
${
addr
.
address
}
]`
:
addr
.
address
return
new
URL
(
`
${
protocol
}
://
${
host
}
:
${
addr
.
port
}
`
)
}
// If this is a string then it is a pipe or Unix socket.
return
addr
}
/**
* Handles the error that occurs in the catch block
* after we try fs.unlink(args.socket).
*
* We extracted into a function so that we could
* test this logic more easily.
*/
export
const
handleArgsSocketCatchError
=
(
error
:
any
)
=>
{
if
(
!
isNodeJSErrnoException
(
error
)
||
error
.
code
!==
"ENOENT"
)
{
throw
Error
(
error
.
message
?
error
.
message
:
error
)
}
}
Back
|
FazBrowse Home
|
New Git URL