Skip to content

Commit

Permalink
Merge pull request #25 from EthianWong/feat/disposeable
Browse files Browse the repository at this point in the history
feat: allow proactively eliminate side effects
  • Loading branch information
GrinZero authored Oct 23, 2024
2 parents 9406375 + f97db9c commit b6d568a
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 46 deletions.
9 changes: 9 additions & 0 deletions README-zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ import { register } from 'node-network-devtools'
process.env.NODE_ENV === 'development' && register()
```

如果需要停止调试网络请求并消除副作用,只需使用 `register` 方法的返回值进行清理。

```typescript
import { register } from 'node-network-devtools'

const unregister = register()
unregister()
```

## 📚 文档

如果遇到任何问题,可以尝试清理`request-centre.lock`文件
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,13 @@ import { register } from 'node-network-devtools'
process.env.NODE_ENV === 'development' && register()
```

To stop debugging network requests and eliminate side effects, just use the return value of the `register` method for cleanup.

```typescript
import { register } from 'node-network-devtools'

const unregister = register()
unregister()
```

![Visitors](https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fgithub.jparrowsec.cn%2FGrinZero%2Fnode-network-devtools&labelColor=%237fa1f7&countColor=%23697689)
85 changes: 41 additions & 44 deletions packages/network-debugger/src/core/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,73 @@
import { RequestDetail } from "../common";
import { headersToObject } from "../utils/map";
import { MainProcess } from "./fork";
import { RequestDetail } from '../common'
import { headersToObject } from '../utils/map'
import { MainProcess } from './fork'

export function proxyFetch(mainProcess: MainProcess) {
if (!globalThis.fetch) {
return;
return
}
const originalFetch = globalThis.fetch;
const originalFetch = globalThis.fetch

globalThis["fetch"] = fetchProxyFactory(originalFetch, mainProcess);
globalThis['fetch'] = fetchProxyFactory(originalFetch, mainProcess)

return () => {
globalThis['fetch'] = originalFetch
}
}

function fetchProxyFactory(fetchFn: typeof fetch, mainProcess: MainProcess) {
return function (request: string | URL | Request, options?: RequestInit) {
const requestDetail = new RequestDetail();
requestDetail.requestStartTime = new Date().getTime();
const requestDetail = new RequestDetail()
requestDetail.requestStartTime = new Date().getTime()

if (typeof request === "string") {
requestDetail.url = request;
if (typeof request === 'string') {
requestDetail.url = request
} else if (request instanceof URL) {
requestDetail.url = request.toString();
requestDetail.url = request.toString()
}

requestDetail.method = options?.method ?? "GET";
requestDetail.requestHeaders = options?.headers ?? {};
requestDetail.requestData = options?.body;
requestDetail.method = options?.method ?? 'GET'
requestDetail.requestHeaders = options?.headers ?? {}
requestDetail.requestData = options?.body

mainProcess.registerRequest(requestDetail);
mainProcess.registerRequest(requestDetail)
return fetchFn(request as string | Request, options)
.then(fetchResponseHandlerFactory(requestDetail, mainProcess))
.catch(fetchErrorHandlerFactory(requestDetail, mainProcess));
};
.catch(fetchErrorHandlerFactory(requestDetail, mainProcess))
}
}

function fetchResponseHandlerFactory(
requestDetail: RequestDetail,
mainProcess: MainProcess
) {
function fetchResponseHandlerFactory(requestDetail: RequestDetail, mainProcess: MainProcess) {
return (response: Response) => {
requestDetail.requestEndTime = new Date().getTime();
requestDetail.responseHeaders = headersToObject(response.headers);
requestDetail.responseStatusCode = response.status || 0;

requestDetail.requestEndTime = new Date().getTime()
requestDetail.responseHeaders = headersToObject(response.headers)
requestDetail.responseStatusCode = response.status || 0

response
.clone()
.arrayBuffer()
.then((buffer) => {
const responseData = Buffer.from(buffer);
requestDetail.responseData = responseData;
requestDetail.responseInfo.dataLength = responseData.length;
const responseData = Buffer.from(buffer)
requestDetail.responseData = responseData
requestDetail.responseInfo.dataLength = responseData.length
// TODO: use content-encoding to determine the actual length
requestDetail.responseInfo.encodedDataLength = responseData.length;
requestDetail.responseInfo.encodedDataLength = responseData.length
})
.finally(() => {
mainProcess.updateRequest(requestDetail);
mainProcess.endRequest(requestDetail);
});
mainProcess.updateRequest(requestDetail)
mainProcess.endRequest(requestDetail)
})

return response;
};
return response
}
}

function fetchErrorHandlerFactory(
requestDetail: RequestDetail,
mainProcess: MainProcess
) {
function fetchErrorHandlerFactory(requestDetail: RequestDetail, mainProcess: MainProcess) {
return (err: unknown) => {
requestDetail.requestEndTime = Date.now();
requestDetail.responseStatusCode = 0;
mainProcess.updateRequest(requestDetail);
mainProcess.endRequest(requestDetail);
throw err;
};
requestDetail.requestEndTime = Date.now()
requestDetail.responseStatusCode = 0
mainProcess.updateRequest(requestDetail)
mainProcess.endRequest(requestDetail)
throw err
}
}
14 changes: 13 additions & 1 deletion packages/network-debugger/src/core/fork.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { IS_DEV_MODE, READY_MESSAGE, RequestDetail } from '../common'
import { type IncomingMessage } from 'http'
import WebSocket from 'ws'
import { fork } from 'child_process'
import { ChildProcess, fork } from 'child_process'
import { __dirname } from '../common'
import { resolve } from 'path'
import { RegisterOptions } from '../common'

export class MainProcess {
private ws: Promise<WebSocket>
private options: RegisterOptions
private cp?: ChildProcess

constructor(props: RegisterOptions) {
this.options = props
Expand Down Expand Up @@ -51,6 +52,7 @@ export class MainProcess {
}

cp.on('message', handleMsg)
this.cp = cp
}

if (IS_DEV_MODE) {
Expand Down Expand Up @@ -111,5 +113,15 @@ export class MainProcess {
})
})
}

public async dispose() {
const ws = await this.ws
ws.removeAllListeners()
ws.terminate()
if (!this.cp) return
this.cp.removeAllListeners()
this.cp.kill()
this.cp = void 0
}
}
export { __dirname }
12 changes: 11 additions & 1 deletion packages/network-debugger/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,21 @@ export async function register(props?: RegisterOptions) {
autoOpenDevtool
})

proxyFetch(mainProcess)
const unsetFetchProxy = proxyFetch(mainProcess)

const originAgentRequests = new WeakMap()
const agents = [http, https]
agents.forEach((agent) => {
originAgentRequests.set(agent, agent.request)
const actualRequestHandlerFn = agent.request
agent.request = requestProxyFactory(actualRequestHandlerFn, agent === https, mainProcess)
})
return () => {
unsetFetchProxy && unsetFetchProxy()
agents.forEach((agent) => {
agent.request = originAgentRequests.get(agent)
originAgentRequests.delete(agent)
})
mainProcess.dispose()
}
}

0 comments on commit b6d568a

Please sign in to comment.