Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbbcd5fd

Browse files
authored
Use Axios client for EventSource (#440)
1 parente01f0e3 commitbbcd5fd

File tree

7 files changed

+105
-29
lines changed

7 files changed

+105
-29
lines changed

‎CHANGELOG.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,43 @@
22

33
##Unreleased
44

5-
- Remove agent singleton so that client TLS certificates are reloaded on every API request.
6-
75
###Fixed
86

7+
- Remove agent singleton so that client TLS certificates are reloaded on every API request.
8+
- Use Axios client to receive event stream so TLS settings are properly applied.
9+
910
##[v1.4.1](https://github.com/coder/vscode-coder/releases/tag/v1.4.1) (2025-02-19)
1011

12+
###Fixed
13+
1114
- Recreate REST client in spots where confirmStart may have waited indefinitely.
1215

1316
##[v1.4.0](https://github.com/coder/vscode-coder/releases/tag/v1.4.0) (2025-02-04)
1417

18+
###Fixed
19+
1520
- Recreate REST client after starting a workspace to ensure fresh TLS certificates.
21+
22+
###Changed
23+
1624
- Use`coder ssh` subcommand in place of`coder vscodessh`.
1725

1826
##[v1.3.10](https://github.com/coder/vscode-coder/releases/tag/v1.3.10) (2025-01-17)
1927

28+
###Fixed
29+
2030
- Fix bug where checking for overridden properties incorrectly converted host name pattern to regular expression.
2131

2232
##[v1.3.9](https://github.com/coder/vscode-coder/releases/tag/v1.3.9) (2024-12-12)
2333

34+
###Fixed
35+
2436
- Only show a login failure dialog for explicit logins (and not autologins).
2537

2638
##[v1.3.8](https://github.com/coder/vscode-coder/releases/tag/v1.3.8) (2024-12-06)
2739

40+
###Changed
41+
2842
- When starting a workspace, shell out to the Coder binary instead of making an
2943
API call. This reduces drift between what the plugin does and the CLI does. As
3044
part of this, the`session_token` file was renamed to`session` since that is

‎package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,10 @@
208208
],
209209
"menus": {
210210
"commandPalette": [
211-
{
212-
"command":"coder.openFromSidebar",
213-
"when":"false"
214-
}
211+
{
212+
"command":"coder.openFromSidebar",
213+
"when":"false"
214+
}
215215
],
216216
"view/title": [
217217
{
@@ -275,7 +275,7 @@
275275
"test:ci":"CI=true yarn test"
276276
},
277277
"devDependencies": {
278-
"@types/eventsource":"^1.1.15",
278+
"@types/eventsource":"^3.0.0",
279279
"@types/glob":"^7.1.3",
280280
"@types/node":"^18.0.0",
281281
"@types/node-forge":"^1.3.11",
@@ -309,7 +309,7 @@
309309
"dependencies": {
310310
"axios":"1.7.7",
311311
"date-fns":"^3.6.0",
312-
"eventsource":"^2.0.2",
312+
"eventsource":"^3.0.5",
313313
"find-process":"^1.4.7",
314314
"jsonc-parser":"^3.3.1",
315315
"memfs":"^4.9.3",

‎src/api-helper.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import{isApiError,isApiErrorResponse}from"coder/site/src/api/errors"
22
import{Workspace,WorkspaceAgent}from"coder/site/src/api/typesGenerated"
3+
import{ErrorEvent}from"eventsource"
34
import{z}from"zod"
45

56
exportfunctionerrToStr(error:unknown,def:string){
@@ -9,6 +10,8 @@ export function errToStr(error: unknown, def: string) {
910
returnerror.response.data.message
1011
}elseif(isApiErrorResponse(error)){
1112
returnerror.message
13+
}elseif(errorinstanceofErrorEvent){
14+
returnerror.code ?`${error.code}:${error.message||def}` :error.message||def
1215
}elseif(typeoferror==="string"&&error.trim().length>0){
1316
returnerror
1417
}

‎src/api.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import{AxiosInstance}from"axios"
12
import{spawn}from"child_process"
23
import{Api}from"coder/site/src/api/api"
34
import{ProvisionerJobLog,Workspace}from"coder/site/src/api/typesGenerated"
5+
import{FetchLikeInit}from"eventsource"
46
importfsfrom"fs/promises"
57
import{ProxyAgent}from"proxy-agent"
68
import*asvscodefrom"vscode"
@@ -90,6 +92,58 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s
9092
returnrestClient
9193
}
9294

95+
/**
96+
* Creates a fetch adapter using an Axios instance that returns streaming responses.
97+
* This can be used with APIs that accept fetch-like interfaces.
98+
*/
99+
exportfunctioncreateStreamingFetchAdapter(axiosInstance:AxiosInstance){
100+
returnasync(url:string|URL,init?:FetchLikeInit)=>{
101+
consturlStr=url.toString()
102+
103+
constresponse=awaitaxiosInstance.request({
104+
url:urlStr,
105+
headers:init?.headersasRecord<string,string>,
106+
responseType:"stream",
107+
validateStatus:()=>true,// Don't throw on any status code
108+
})
109+
conststream=newReadableStream({
110+
start(controller){
111+
response.data.on("data",(chunk:Buffer)=>{
112+
controller.enqueue(chunk)
113+
})
114+
115+
response.data.on("end",()=>{
116+
controller.close()
117+
})
118+
119+
response.data.on("error",(err:Error)=>{
120+
controller.error(err)
121+
})
122+
},
123+
124+
cancel(){
125+
response.data.destroy()
126+
returnPromise.resolve()
127+
},
128+
})
129+
130+
return{
131+
body:{
132+
getReader:()=>stream.getReader(),
133+
},
134+
url:urlStr,
135+
status:response.status,
136+
redirected:response.request.res.responseUrl!==urlStr,
137+
headers:{
138+
get:(name:string)=>{
139+
constvalue=response.headers[name.toLowerCase()]
140+
returnvalue===undefined ?null :String(value)
141+
},
142+
},
143+
}
144+
}
145+
}
146+
93147
/**
94148
* Start or update a workspace and return the updated workspace.
95149
*/
@@ -182,6 +236,7 @@ export async function waitForBuild(
182236
path+=`&after=${logs[logs.length-1].id}`
183237
}
184238

239+
constagent=awaitcreateHttpAgent()
185240
awaitnewPromise<void>((resolve,reject)=>{
186241
try{
187242
constbaseUrl=newURL(baseUrlRaw)
@@ -194,6 +249,7 @@ export async function waitForBuild(
194249
|undefined,
195250
},
196251
followRedirects:true,
252+
agent:agent,
197253
})
198254
socket.binaryType="nodebuffer"
199255
socket.on("message",(data)=>{

‎src/workspaceMonitor.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import{Api}from"coder/site/src/api/api"
22
import{Workspace}from"coder/site/src/api/typesGenerated"
33
import{formatDistanceToNowStrict}from"date-fns"
4-
importEventSourcefrom"eventsource"
4+
import{EventSource}from"eventsource"
55
import*asvscodefrom"vscode"
6+
import{createStreamingFetchAdapter}from"./api"
67
import{errToStr}from"./api-helper"
78
import{Storage}from"./storage"
89

@@ -40,16 +41,11 @@ export class WorkspaceMonitor implements vscode.Disposable {
4041
){
4142
this.name=`${workspace.owner_name}/${workspace.name}`
4243
consturl=this.restClient.getAxiosInstance().defaults.baseURL
43-
consttoken=this.restClient.getAxiosInstance().defaults.headers.common["Coder-Session-Token"]as
44-
|string
45-
|undefined
4644
constwatchUrl=newURL(`${url}/api/v2/workspaces/${workspace.id}/watch`)
4745
this.storage.writeToCoderOutputChannel(`Monitoring${this.name}...`)
4846

4947
consteventSource=newEventSource(watchUrl.toString(),{
50-
headers:{
51-
"Coder-Session-Token":token,
52-
},
48+
fetch:createStreamingFetchAdapter(this.restClient.getAxiosInstance()),
5349
})
5450

5551
eventSource.addEventListener("data",(event)=>{
@@ -64,7 +60,7 @@ export class WorkspaceMonitor implements vscode.Disposable {
6460
})
6561

6662
eventSource.addEventListener("error",(event)=>{
67-
this.notifyError(event.data)
63+
this.notifyError(event)
6864
})
6965

7066
// Store so we can close in dispose().

‎src/workspacesProvider.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import{Api}from"coder/site/src/api/api"
22
import{Workspace,WorkspaceAgent}from"coder/site/src/api/typesGenerated"
3-
importEventSourcefrom"eventsource"
3+
import{EventSource}from"eventsource"
44
import*aspathfrom"path"
55
import*asvscodefrom"vscode"
6+
import{createStreamingFetchAdapter}from"./api"
67
import{
78
AgentMetadataEvent,
89
AgentMetadataEventSchemaArray,
@@ -228,12 +229,9 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
228229
functionmonitorMetadata(agentId:WorkspaceAgent["id"],restClient:Api):AgentWatcher{
229230
// TODO: Is there a better way to grab the url and token?
230231
consturl=restClient.getAxiosInstance().defaults.baseURL
231-
consttoken=restClient.getAxiosInstance().defaults.headers.common["Coder-Session-Token"]asstring|undefined
232232
constmetadataUrl=newURL(`${url}/api/v2/workspaceagents/${agentId}/watch-metadata`)
233233
consteventSource=newEventSource(metadataUrl.toString(),{
234-
headers:{
235-
"Coder-Session-Token":token,
236-
},
234+
fetch:createStreamingFetchAdapter(restClient.getAxiosInstance()),
237235
})
238236

239237
letdisposed=false

‎yarn.lock

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,12 @@
537537
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
538538
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
539539

540-
"@types/eventsource@^1.1.15":
541-
version "1.1.15"
542-
resolved "https://registry.yarnpkg.com/@types/eventsource/-/eventsource-1.1.15.tgz#949383d3482e20557cbecbf3b038368d94b6be27"
543-
integrity sha512-XQmGcbnxUNa06HR3VBVkc9+A2Vpi9ZyLJcdS5dwaQQ/4ZMWFO+5c90FnMUpbtMZwB/FChoYHwuVg8TvkECacTA==
540+
"@types/eventsource@^3.0.0":
541+
version "3.0.0"
542+
resolved "https://registry.yarnpkg.com/@types/eventsource/-/eventsource-3.0.0.tgz#6b1b50c677032fd3be0b5c322e8ae819b3df62eb"
543+
integrity sha512-yEhFj31FTD29DtNeqePu+A+lD6loRef6YOM5XfN1kUwBHyy2DySGlA3jJU+FbQSkrfmlBVluf2Dub/OyReFGKA==
544+
dependencies:
545+
eventsource "*"
544546

545547
"@types/glob@^7.1.3":
546548
version "7.2.0"
@@ -2529,10 +2531,17 @@ events@^3.2.0:
25292531
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
25302532
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
25312533

2532-
eventsource@^2.0.2:
2533-
version "2.0.2"
2534-
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508"
2535-
integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==
2534+
eventsource-parser@^3.0.0:
2535+
version "3.0.0"
2536+
resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.0.tgz#9303e303ef807d279ee210a17ce80f16300d9f57"
2537+
integrity sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==
2538+
2539+
eventsource@*, eventsource@^3.0.5:
2540+
version "3.0.5"
2541+
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.5.tgz#0cae1eee2d2c75894de8b02a91d84e5c57f0cc5a"
2542+
integrity sha512-LT/5J605bx5SNyE+ITBDiM3FxffBiq9un7Vx0EwMDM3vg8sWKx/tO2zC+LMqZ+smAM0F2hblaDZUVZF0te2pSw==
2543+
dependencies:
2544+
eventsource-parser "^3.0.0"
25362545

25372546
exec@^0.2.1:
25382547
version "0.2.1"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp