3
3
/**
4
4
* static files (404.html, sw.js, conf.js)
5
5
*/
6
- const ASSET_URL = 'https://zjcqoo .github.io'
6
+ const ASSET_URL = 'https://etherdream .github.io/jsproxy '
7
7
8
- const JS_VER = 8
8
+ const JS_VER = 10
9
9
const MAX_RETRY = 1
10
10
11
-
11
+ /** @type { RequestInit } */
12
12
const PREFLIGHT_INIT = {
13
13
status : 204 ,
14
14
headers : new Headers ( {
15
15
'access-control-allow-origin' : '*' ,
16
16
'access-control-allow-methods' : 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS' ,
17
- 'access-control-allow-headers' : '--raw-info,--level,--url,--referer,--cookie,--origin,--ext,--aceh,--ver,--type,--mode,accept,accept-charset,accept-encoding,accept-language,accept-datetime,authorization,cache-control,content-length,content-type,date,if-match,if-modified-since,if-none-match,if-range,if-unmodified-since,max-forwards,pragma,range,te,upgrade,upgrade-insecure-requests,x-requested-with,chrome-proxy,purpose' ,
18
17
'access-control-max-age' : '1728000' ,
19
18
} ) ,
20
19
}
21
20
22
21
/**
23
- * @param {string } message
22
+ * @param {any } body
24
23
* @param {number } status
25
- * @param {any } headers
24
+ * @param {Object<string, string> } headers
26
25
*/
27
- function makeRes ( message , status = 200 , headers = { } ) {
28
- headers [ 'cache-control' ] = 'no-cache'
29
- headers [ 'vary' ] = '--url'
26
+ function makeRes ( body , status = 200 , headers = { } ) {
27
+ headers [ '--ver' ] = JS_VER
30
28
headers [ 'access-control-allow-origin' ] = '*'
31
- return new Response ( message , { status, headers} )
29
+ return new Response ( body , { status, headers} )
30
+ }
31
+
32
+
33
+ /**
34
+ * @param {string } urlStr
35
+ */
36
+ function newUrl ( urlStr ) {
37
+ try {
38
+ return new URL ( urlStr )
39
+ } catch ( err ) {
40
+ return null
41
+ }
32
42
}
33
43
34
44
35
45
addEventListener ( 'fetch' , e => {
36
46
const ret = fetchHandler ( e )
37
- . catch ( err => makeRes ( 'cfworker error:' + err , 502 ) )
47
+ . catch ( err => makeRes ( 'cfworker error:\n ' + err . stack , 502 ) )
38
48
e . respondWith ( ret )
39
49
} )
40
50
41
51
42
- function fetchHandler ( e ) {
52
+ /**
53
+ * @param {FetchEvent } e
54
+ */
55
+ async function fetchHandler ( e ) {
43
56
const req = e . request
44
57
const urlStr = req . url
45
58
const urlObj = new URL ( urlStr )
59
+ const path = urlObj . href . substr ( urlObj . origin . length )
46
60
47
61
if ( urlObj . protocol === 'http:' ) {
48
62
urlObj . protocol = 'https:'
@@ -52,25 +66,29 @@ function fetchHandler(e) {
52
66
} )
53
67
}
54
68
55
- switch ( urlObj . pathname ) {
69
+ if ( path . startsWith ( '/http/' ) ) {
70
+ return httpHandler ( req , path . substr ( 6 ) )
71
+ }
72
+
73
+ switch ( path ) {
56
74
case '/http' :
57
- return httpHandler ( req )
75
+ return makeRes ( '请更新 cfworker 到最新版本!' )
58
76
case '/ws' :
59
77
return makeRes ( 'not support' , 400 )
60
78
case '/works' :
61
79
return makeRes ( 'it works' )
62
80
default :
63
81
// static files
64
- return fetch ( ASSET_URL + urlObj . pathname )
82
+ return fetch ( ASSET_URL + path )
65
83
}
66
84
}
67
85
68
86
69
-
70
87
/**
71
88
* @param {Request } req
89
+ * @param {string } pathname
72
90
*/
73
- async function httpHandler ( req ) {
91
+ function httpHandler ( req , pathname ) {
74
92
const reqHdrRaw = req . headers
75
93
if ( reqHdrRaw . has ( 'x-jsproxy' ) ) {
76
94
return Response . error ( )
@@ -83,8 +101,6 @@ async function httpHandler(req) {
83
101
return new Response ( null , PREFLIGHT_INIT )
84
102
}
85
103
86
- let urlObj = null
87
- let extHdrs = null
88
104
let acehOld = false
89
105
let rawSvr = ''
90
106
let rawLen = ''
@@ -93,52 +109,51 @@ async function httpHandler(req) {
93
109
const reqHdrNew = new Headers ( reqHdrRaw )
94
110
reqHdrNew . set ( 'x-jsproxy' , '1' )
95
111
96
- for ( const [ k , v ] of reqHdrRaw . entries ( ) ) {
97
- if ( ! k . startsWith ( '--' ) ) {
98
- continue
99
- }
100
- reqHdrNew . delete ( k )
101
-
102
- const k2 = k . substr ( 2 )
103
- switch ( k2 ) {
104
- case 'url' :
105
- urlObj = new URL ( v )
106
- break
107
- case 'aceh' :
108
- acehOld = true
109
- break
110
- case 'raw-info' :
111
- [ rawSvr , rawLen , rawEtag ] = v . split ( '|' )
112
- break
113
- case 'level' :
114
- case 'mode' :
115
- case 'type' :
116
- break
117
- case 'ext' :
118
- extHdrs = JSON . parse ( v )
119
- break
120
- default :
112
+ // 此处逻辑和 http-dec-req-hdr.lua 大致相同
113
+ // https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua
114
+ const refer = reqHdrNew . get ( 'referer' )
115
+ const query = refer . substr ( refer . indexOf ( '?' ) + 1 )
116
+ if ( ! query ) {
117
+ return makeRes ( 'missing params' , 403 )
118
+ }
119
+ const param = new URLSearchParams ( query )
120
+
121
+ for ( const [ k , v ] of Object . entries ( param ) ) {
122
+ if ( k . substr ( 0 , 2 ) === '--' ) {
123
+ // 系统信息
124
+ switch ( k . substr ( 2 ) ) {
125
+ case 'aceh' :
126
+ acehOld = true
127
+ break
128
+ case 'raw-info' :
129
+ [ rawSvr , rawLen , rawEtag ] = v . split ( '|' )
130
+ break
131
+ }
132
+ } else {
133
+ // 还原 HTTP 请求头
121
134
if ( v ) {
122
- reqHdrNew . set ( k2 , v )
135
+ reqHdrNew . set ( k , v )
123
136
} else {
124
- reqHdrNew . delete ( k2 )
137
+ reqHdrNew . delete ( k )
125
138
}
126
- break
127
139
}
128
140
}
129
- if ( extHdrs ) {
130
- for ( const [ k , v ] of Object . entries ( extHdrs ) ) {
131
- reqHdrNew . set ( k , v )
132
- }
141
+ if ( ! param . has ( 'referer' ) ) {
142
+ reqHdrNew . delete ( 'referer' )
133
143
}
144
+
145
+ // cfworker 会把路径中的 `//` 合并成 `/`
146
+ const urlStr = pathname . replace ( / ^ ( h t t p s ? ) : \/ + / , '$1://' )
147
+ const urlObj = newUrl ( urlStr )
134
148
if ( ! urlObj ) {
135
- return makeRes ( 'missing url param' , 403 )
149
+ return makeRes ( 'invalid proxy url: ' + urlStr , 403 )
136
150
}
137
151
138
152
/** @type {RequestInit } */
139
153
const reqInit = {
140
154
method : req . method ,
141
155
headers : reqHdrNew ,
156
+ redirect : 'manual' ,
142
157
}
143
158
if ( req . method === 'POST' ) {
144
159
reqInit . body = req . body
@@ -159,7 +174,6 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
159
174
const resHdrNew = new Headers ( resHdrOld )
160
175
161
176
let expose = '*'
162
- let vary = '--url'
163
177
164
178
for ( const [ k , v ] of resHdrOld . entries ( ) ) {
165
179
if ( k === 'access-control-allow-origin' ||
@@ -174,9 +188,6 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
174
188
}
175
189
resHdrNew . delete ( k )
176
190
}
177
- else if ( k === 'vary' ) {
178
- vary = vary + ',' + v
179
- }
180
191
else if ( acehOld &&
181
192
k !== 'cache-control' &&
182
193
k !== 'content-language' &&
@@ -206,8 +217,9 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
206
217
return proxy ( urlObj , reqInit , acehOld , rawLen , retryTimes + 1 )
207
218
}
208
219
}
209
- return makeRes ( 'error' , 400 , {
210
- '--error' : 'bad len:' + newLen
220
+ return makeRes ( res . body , 400 , {
221
+ '--error' : `bad len: ${ newLen } , except: ${ rawLen } ` ,
222
+ 'access-control-expose-headers' : '--error' ,
211
223
} )
212
224
}
213
225
@@ -220,12 +232,12 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
220
232
221
233
resHdrNew . set ( 'access-control-expose-headers' , expose )
222
234
resHdrNew . set ( 'access-control-allow-origin' , '*' )
223
- resHdrNew . set ( 'vary' , vary )
224
235
resHdrNew . set ( '--s' , status )
225
236
resHdrNew . set ( '--ver' , JS_VER )
226
237
227
238
resHdrNew . delete ( 'content-security-policy' )
228
239
resHdrNew . delete ( 'content-security-policy-report-only' )
240
+ resHdrNew . delete ( 'clear-site-data' )
229
241
230
242
if ( status === 301 ||
231
243
status === 302 ||
0 commit comments