Skip to content

Commit 7af4937

Browse files
committed
feat: add chunkTemplate config
1 parent 5415209 commit 7af4937

File tree

7 files changed

+75
-47
lines changed

7 files changed

+75
-47
lines changed

readme-zh_CN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@
9898
|redirectUrl|string|重定向链接,不能和url一样,会死循环|
9999
|groupId|string|分组id,相同的id会被分配到相同的工作空间|
100100
|chunks|string[]|设置event-source数据源,response、responseText会失效|
101-
|chunkSpeed|number|设置数据吐出的间隔,默认1_000|
101+
|chunkInterval|number|设置数据吐出的间隔,默认1_000|
102+
|chunkTemplate|number|设置数据的格式,默认`data: $1\n\n`|
102103

103104
### code面板
104105
通过指定的hooks来动态的修改数据,支持的hooks有

readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ How to solve the above problems? If you can intercept and modify the data before
101101
|redirectUrl|string|cannot be the same as the url, will cause a loop|
102102
|groupId|string|the same group can be used a workspace|
103103
|chunks|string[]|set event-source data source,response、responseText would be overrided|
104-
|chunkSpeed|number|set the interval of chunk,default 1_000|
104+
|chunkInterval|number|set the interval of chunk,default 1_000|
105+
|chunkTemplate|number|set the chunk format,default `data: $1\n\n`|
105106

106107
### Code Panel
107108
call hooks function to modify data, support there hooks

src/App.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export interface MatchRule {
5151
code?: string
5252
redirectUrl?: string
5353
chunks?: string[]
54-
chunkSpeed?: number
54+
chunkInterval?: number
55+
chunkTemplate?: string
5556
}
5657

5758
if (!process.env.VITE_LOCAL) {
@@ -79,7 +80,8 @@ const fields = [
7980
'response',
8081
'responseText',
8182
'chunks',
82-
'chunkSpeed',
83+
'chunkInterval',
84+
'chunkTemplate',
8385
]
8486

8587
const isDarkTheme = window.matchMedia("(prefers-color-scheme: dark)").matches

src/components/MainEditor/validator.ts

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ export const ConfigSchema: JSONSchema7 = {
9393
},
9494
chunks: {
9595
type: 'array',
96-
items: {
97-
type: 'string'
98-
}
9996
},
100-
chunkSpeed: {
97+
chunkInterval: {
10198
type: 'number'
99+
},
100+
chunkTemplate: {
101+
type: 'string'
102102
}
103103
},
104104
}
@@ -179,29 +179,29 @@ export const SettingSchema: JSONSchema7 = {
179179
dark: {
180180
type: 'boolean'
181181
},
182-
proxy: {
183-
type: 'object',
184-
patternProperties: {
185-
".+": {
186-
oneOf: [
187-
{
188-
type: 'string'
189-
},
190-
{
191-
type: 'object',
192-
required: ['target'],
193-
properties: {
194-
target: {
195-
type: 'string'
196-
},
197-
rewrite: {
198-
type: 'string'
199-
}
200-
}
201-
}
202-
]
203-
}
204-
}
205-
}
182+
// proxy: {
183+
// type: 'object',
184+
// patternProperties: {
185+
// ".+": {
186+
// oneOf: [
187+
// {
188+
// type: 'string'
189+
// },
190+
// {
191+
// type: 'object',
192+
// required: ['target'],
193+
// properties: {
194+
// target: {
195+
// type: 'string'
196+
// },
197+
// rewrite: {
198+
// type: 'string'
199+
// }
200+
// }
201+
// }
202+
// ]
203+
// }
204+
// }
205+
// }
206206
}
207207
}

src/injected/proxy/fetch.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* The AGPL License (AGPL)
33
* Copyright (c) 2022 hans000
44
*/
5-
import { asyncGenerator, delayRun, tryToProxyUrl } from "../../tools";
5+
import { asyncGenerator, delayRun, formatChunk, tryToProxyUrl } from "../../tools";
66
import { log } from "../../tools/log";
77
import { parseUrl } from "../../tools";
88
import { Options, __global__ } from "./globalVar";
@@ -21,7 +21,7 @@ export function proxyFetch(options: Options) {
2121

2222
const proxyFetch = new Proxy(__global__.NativeFetch, {
2323
async apply(target, thisArg, args) {
24-
const [input, init] = args
24+
const [input, init] = args as [Request | URL | string, RequestInit]
2525
const isRequest = input instanceof Request
2626
const req = isRequest ? input.clone() : new Request(input.toString(), init)
2727
const url = isRequest
@@ -35,6 +35,19 @@ export function proxyFetch(options: Options) {
3535
type: 'fetch',
3636
params: [...url.searchParams.entries()],
3737
})
38+
39+
if (matchItem?.requestHeaders) {
40+
Object.entries(matchItem.requestHeaders).forEach(([key, value]) => {
41+
if (init.headers instanceof Headers) {
42+
init.headers.append(key, value)
43+
} else if (Array.isArray(init.headers)) {
44+
init.headers.push([key, value])
45+
} else if (typeof init.headers === 'object') {
46+
init.headers[key] = value
47+
}
48+
})
49+
}
50+
3851
const realFetch = __global__.PageFetch || target
3952
const proxyUrl = tryToProxyUrl(input, __global__.options.proxy)
4053
const proxyInput = isRequest ? new Request(proxyUrl, init) : proxyUrl
@@ -49,26 +62,28 @@ export function proxyFetch(options: Options) {
4962
...init,
5063
})
5164
}
52-
const realResponse = options.faked
53-
? new Response(new Blob(['null']))
65+
66+
const chunks = matchItem.chunks || []
67+
const isEventSource = !!chunks.length
68+
const realResponse = (options.faked || isEventSource)
69+
? new Response(new Blob(['null']), init)
5470
: await realFetch.call(thisArg, proxyInput, init)
5571
const response = await onFetchIntercept(matchItem)(realResponse)
5672

5773
return new Promise(resolve => {
5874
delayRun(async () => {
5975
let res: Response = response || realResponse
6076

61-
const chunks = matchItem.chunks || []
62-
const isEventSource = !!chunks.length
6377
if (isEventSource) {
6478
res = new Response(new ReadableStream({
6579
async start(controller) {
66-
for await (const value of asyncGenerator(chunks, matchItem.chunkSpeed)) {
67-
controller.enqueue(new TextEncoder().encode(value));
80+
for await (const value of asyncGenerator(chunks, matchItem.chunkInterval)) {
81+
const str = formatChunk(value, matchItem.chunkTemplate)
82+
controller.enqueue(new TextEncoder().encode(str));
6883
}
6984
controller.close();
7085
},
71-
}))
86+
}), init)
7287
}
7388

7489
resolve(res)

src/injected/proxy/handle.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import { MatchRule } from "../../App"
7-
import { asyncGenerator, delayRun, modifyXhrProto, modifyXhrProtoProps, toTitleCase, tryToProxyUrl } from "../../tools"
7+
import { asyncGenerator, delayRun, formatChunk, modifyXhrProto, modifyXhrProtoProps, toTitleCase, tryToProxyUrl } from "../../tools"
88
import { log } from "../../tools/log"
99
import { parseUrl, parseXML, stringifyHeaders } from "../../tools"
1010
import { HttpStatusCodes } from "./constants"
@@ -203,9 +203,10 @@ export function proxyFakeXhrInstance(inst: ProxyXMLHttpRequest, options: Options
203203
if (isEventSource) {
204204
// @ts-ignore inst field has been proxy
205205
inst.responseText = ''
206-
for await (const item of asyncGenerator(inst._matchItem.chunks, inst._matchItem.chunkSpeed)) {
206+
for await (const item of asyncGenerator(inst._matchItem.chunks, inst._matchItem.chunkInterval)) {
207+
const str = formatChunk(item, matchItem.chunkTemplate)
207208
// @ts-ignore inst field has been proxy
208-
inst.responseText += item
209+
inst.responseText += str
209210
handleStateChange.call(inst, XMLHttpRequest.LOADING)
210211
}
211212
}

src/tools/index.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ export function createSymbol(attr: string) {
66
return Symbol.for(attr)
77
}
88

9-
export async function* asyncGenerator(data: string[], delay = 1000) {
10-
for (const item of data) {
9+
export function formatChunk(chunk: string, tpl = 'data: $1\n\n') {
10+
return tpl.replace('$1', chunk)
11+
}
12+
13+
export async function* asyncGenerator(data: unknown[], delay = 1000) {
14+
const list = data.map(item => typeof item !== 'string' ? JSON.stringify(item) : item)
15+
for (const item of list) {
1116
await new Promise(resolve => setTimeout(resolve, delay))
1217
yield item
1318
}
@@ -235,10 +240,13 @@ export function toTitleCase(str = '') {
235240
return str.replace(/\b[a-z]/g, c => c.toUpperCase())
236241
}
237242

238-
export function tryToProxyUrl(url: string | URL, proxy: Record<string, string | {
243+
export function tryToProxyUrl(url: string | URL | Request, proxy: Record<string, string | {
239244
target: string
240245
rewrite?: string
241246
}> = {}) {
247+
if (url instanceof Request) {
248+
return url.url
249+
}
242250
const urlObj = url instanceof URL ? url : parseUrl(url)
243251
for (const [name, value] of Object.entries(proxy)) {
244252
try {

0 commit comments

Comments
 (0)