mirror of
https://github.com/EtherDream/jsproxy
synced 2024-11-22 01:49:01 +00:00
This commit is contained in:
parent
5ca89b3e7b
commit
3391d1df8b
9
api.conf
9
api.conf
@ -27,15 +27,18 @@ location = /preflight {
|
||||
more_set_headers
|
||||
'access-control-allow-origin: *'
|
||||
'access-control-allow-methods: GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS'
|
||||
'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'
|
||||
'access-control-max-age: 1728000'
|
||||
;
|
||||
return 204;
|
||||
}
|
||||
|
||||
# 该接口已作废
|
||||
location = /http {
|
||||
rewrite ^ /error?msg=API_OBSOLETED;
|
||||
}
|
||||
|
||||
# HTTP(S) Proxy
|
||||
location = /http {
|
||||
location /http/ {
|
||||
# see ./allowed-sites.conf
|
||||
if ($_origin_id = '') {
|
||||
rewrite ^ /error?msg=ORIGIN_NOT_ALLOWED;
|
||||
@ -47,7 +50,7 @@ location = /http {
|
||||
proxy_set_header Connection $http_connection;
|
||||
|
||||
|
||||
if ($http_access_control_request_headers) {
|
||||
if ($http_access_control_request_methods) {
|
||||
rewrite ^ /preflight;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
listen 8443 ssl http2;
|
||||
ssl_certificate cert/etherdream.com/ecc.cer;
|
||||
ssl_certificate_key cert/etherdream.com/ecc.key;
|
@ -23,29 +23,12 @@
|
||||
|
||||
如果不够用,可注册多个 Worker,在 `conf.js` 中配置多线路负载均衡。或者升级到 $5 的高级版本,每月可用 1000 万次请求(超出部分 $0.5/百万次请求)。
|
||||
|
||||
如果远不够用,建议和服务器组合使用。因为 cfworker 是按请求次数计费的,所以小文件更适合通过服务器代理,大文件走 cfworker 才合算。可参考下面的 `加速功能`。
|
||||
|
||||
|
||||
# 修改配置
|
||||
|
||||
默认情况下,静态资源从 `https://zjcqoo.github.io` 反向代理,可通过代码中 `ASSET_URL` 配置,从而可使用自定义的 `conf.js` 配置。
|
||||
|
||||
|
||||
# 加速功能
|
||||
|
||||
如果你已有服务器,也可通过 CloudFlare Worker 分担大文件的代理。
|
||||
|
||||
前端修改:`conf.js` 的 `cfworker` 节点 `lines` 配置。
|
||||
|
||||
后端修改:`lua/http-enc-res-hdr.lua` 的 [114-116 行](https://github.com/EtherDream/jsproxy/blob/master/lua/http-enc-res-hdr.lua#L114-L116) 注释打开,重启服务生效。
|
||||
|
||||
可在 [84行](https://github.com/EtherDream/jsproxy/blob/master/lua/http-enc-res-hdr.lua#L84) 处修改大于多少字节的静态资源走加速。
|
||||
|
||||
该功能目前还在实验中,有问题或者更好的思路可交流。
|
||||
|
||||
(推荐下行流量免费且不限速的服务器,可节省大量费用)
|
||||
|
||||
|
||||
# 存在问题
|
||||
|
||||
* WebSocket 代理尚未实现
|
||||
|
@ -25,8 +25,6 @@ const PREFLIGHT_INIT = {
|
||||
* @param {Object<string, string>} headers
|
||||
*/
|
||||
function makeRes(body, status = 200, headers = {}) {
|
||||
headers['cache-control'] = 'no-cache'
|
||||
headers['vary'] = '--url'
|
||||
headers['--ver'] = JS_VER
|
||||
headers['access-control-allow-origin'] = '*'
|
||||
return new Response(body, {status, headers})
|
||||
@ -47,6 +45,7 @@ async function fetchHandler(e) {
|
||||
const req = e.request
|
||||
const urlStr = req.url
|
||||
const urlObj = new URL(urlStr)
|
||||
const {pathname} = urlObj
|
||||
|
||||
if (urlObj.protocol === 'http:') {
|
||||
urlObj.protocol = 'https:'
|
||||
@ -56,16 +55,18 @@ async function fetchHandler(e) {
|
||||
})
|
||||
}
|
||||
|
||||
switch (urlObj.pathname) {
|
||||
case '/http':
|
||||
if (pathname.startsWith('/http')) {
|
||||
return httpHandler(req)
|
||||
}
|
||||
|
||||
switch (pathname) {
|
||||
case '/ws':
|
||||
return makeRes('not support', 400)
|
||||
case '/works':
|
||||
return makeRes('it works')
|
||||
default:
|
||||
// static files
|
||||
return fetch(ASSET_URL + urlObj.pathname)
|
||||
return fetch(ASSET_URL + pathname)
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,8 +87,13 @@ function httpHandler(req) {
|
||||
return new Response(null, PREFLIGHT_INIT)
|
||||
}
|
||||
|
||||
let urlObj = null
|
||||
let extHdrs = null
|
||||
const urlStr = req.url.substr(6)
|
||||
try {
|
||||
var urlObj = new URL(urlStr)
|
||||
} catch (err) {
|
||||
return makeRes('invalid url: ' + urlStr, 403)
|
||||
}
|
||||
|
||||
let acehOld = false
|
||||
let rawSvr = ''
|
||||
let rawLen = ''
|
||||
@ -96,46 +102,34 @@ function httpHandler(req) {
|
||||
const reqHdrNew = new Headers(reqHdrRaw)
|
||||
reqHdrNew.set('x-jsproxy', '1')
|
||||
|
||||
for (const [k, v] of reqHdrRaw.entries()) {
|
||||
if (!k.startsWith('--')) {
|
||||
continue
|
||||
}
|
||||
reqHdrNew.delete(k)
|
||||
// 此处逻辑和 http-dec-req-hdr.lua 大致相同
|
||||
// https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua
|
||||
const {sys, ext} = JSON.parse(reqHdrNew.get('accept'))
|
||||
|
||||
const k2 = k.substr(2)
|
||||
switch (k2) {
|
||||
case 'url':
|
||||
urlObj = new URL(v)
|
||||
break
|
||||
// 系统信息
|
||||
for (const [k, v] of Object.entries(sys)) {
|
||||
switch (k) {
|
||||
case 'aceh':
|
||||
acehOld = true
|
||||
break
|
||||
case 'raw-info':
|
||||
[rawSvr, rawLen, rawEtag] = v.split('|')
|
||||
break
|
||||
case 'level':
|
||||
case 'mode':
|
||||
case 'type':
|
||||
break
|
||||
case 'ext':
|
||||
extHdrs = JSON.parse(v)
|
||||
break
|
||||
default:
|
||||
if (v) {
|
||||
reqHdrNew.set(k2, v)
|
||||
} else {
|
||||
reqHdrNew.delete(k2)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if (extHdrs) {
|
||||
for (const [k, v] of Object.entries(extHdrs)) {
|
||||
reqHdrNew.set(k, v)
|
||||
|
||||
// 原始 HTTP 字段
|
||||
let hasRawAccept = false
|
||||
|
||||
for (const [k, v] of Object.entries(ext)) {
|
||||
if (k === 'accept') {
|
||||
hasRawAccept = true
|
||||
}
|
||||
reqHdrNew.set(k, v)
|
||||
}
|
||||
if (!urlObj) {
|
||||
return makeRes('missing url param', 403)
|
||||
|
||||
if (!hasRawAccept) {
|
||||
reqHdrNew.delete('accept')
|
||||
}
|
||||
|
||||
/** @type {RequestInit} */
|
||||
@ -163,7 +157,6 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
|
||||
const resHdrNew = new Headers(resHdrOld)
|
||||
|
||||
let expose = '*'
|
||||
let vary = '--url'
|
||||
|
||||
for (const [k, v] of resHdrOld.entries()) {
|
||||
if (k === 'access-control-allow-origin' ||
|
||||
@ -178,9 +171,6 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
|
||||
}
|
||||
resHdrNew.delete(k)
|
||||
}
|
||||
else if (k === 'vary') {
|
||||
vary = vary + ',' + v
|
||||
}
|
||||
else if (acehOld &&
|
||||
k !== 'cache-control' &&
|
||||
k !== 'content-language' &&
|
||||
@ -225,7 +215,6 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
|
||||
|
||||
resHdrNew.set('access-control-expose-headers', expose)
|
||||
resHdrNew.set('access-control-allow-origin', '*')
|
||||
resHdrNew.set('vary', vary)
|
||||
resHdrNew.set('--s', status)
|
||||
resHdrNew.set('--ver', JS_VER)
|
||||
|
||||
|
@ -1,20 +1,18 @@
|
||||
-- 功能:还原 HTTP 请求头
|
||||
-- 阶段:access_by_lua
|
||||
-- 还原 HTTP 请求头
|
||||
-- 前端只保留简单字段(防止出现 preflight),
|
||||
-- 其余字段及系统信息,存储在 Accept 字段里(JSON 格式)。
|
||||
|
||||
local cjson = require('cjson')
|
||||
local hdrs, err = ngx.req.get_headers()
|
||||
local extHdrs
|
||||
ngx.log(ngx.ALERT, 'accept:' .. hdrs['accept'])
|
||||
local info = ngx.unescape_uri(hdrs['accept'])
|
||||
local json = cjson.decode(info)
|
||||
|
||||
for k, v in pairs(hdrs) do
|
||||
if k:sub(1, 2) ~= '--' then
|
||||
goto continue
|
||||
end
|
||||
-- 系统信息
|
||||
local sys = json['sys']
|
||||
|
||||
ngx.req.clear_header(k)
|
||||
k = k:sub(3)
|
||||
|
||||
if k == 'url' then
|
||||
ngx.var._url = v
|
||||
elseif k == 'ver' then
|
||||
for k, v in pairs(sys) do
|
||||
if k == 'ver' then
|
||||
ngx.var._ver = v
|
||||
elseif k == 'type' then
|
||||
ngx.var._type = v
|
||||
@ -25,20 +23,25 @@ for k, v in pairs(hdrs) do
|
||||
elseif k == 'level' then
|
||||
ngx.var._level = v
|
||||
ngx.ctx._level = tonumber(v)
|
||||
elseif k == 'ext' then
|
||||
extHdrs = require('cjson').decode(v)
|
||||
else
|
||||
if k == 'referer' then
|
||||
ngx.var._ref = v
|
||||
end
|
||||
ngx.req.set_header(k, v)
|
||||
end
|
||||
|
||||
::continue::
|
||||
end
|
||||
|
||||
if extHdrs then
|
||||
for k, v in pairs(extHdrs) do
|
||||
ngx.req.set_header(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
-- 原始 HTTP 字段
|
||||
local ext = json['ext']
|
||||
local hasRawAccept = false
|
||||
|
||||
for k, v in pairs(ext) do
|
||||
if k == 'accept' then
|
||||
hasRawAccept = true
|
||||
elseif k == 'referer' then
|
||||
ngx.var._ref = v
|
||||
end
|
||||
ngx.req.set_header(k, v)
|
||||
end
|
||||
|
||||
if not hasRawAccept then
|
||||
ngx.req.clear_header('accept')
|
||||
end
|
||||
|
||||
-- 删除 URL 的 '/http/' 前缀
|
||||
ngx.var._url = ngx.var.request_uri:sub(7)
|
@ -9,9 +9,6 @@ local expose = '*'
|
||||
-- 该值为 true 表示浏览器不支持 aceh: *,需返回详细的头部列表
|
||||
local detail = ngx.ctx._acehOld
|
||||
|
||||
-- 由于接口路径固定,为避免被缓存,以请求头的 --url 值区分缓存
|
||||
local vary = '--url'
|
||||
|
||||
|
||||
local function addHdr(k, v)
|
||||
ngx.header[k] = v
|
||||
@ -32,7 +29,6 @@ local function flushHdr()
|
||||
|
||||
ngx.header['access-control-expose-headers'] = expose
|
||||
ngx.header['access-control-allow-origin'] = '*'
|
||||
ngx.header['vary'] = vary
|
||||
|
||||
local status = ngx.status
|
||||
|
||||
@ -57,15 +53,6 @@ local function flushHdr()
|
||||
end
|
||||
|
||||
|
||||
local function addVary(v)
|
||||
if type(v) == 'table' then
|
||||
vary = vary .. ',' .. table.concat(v, ',')
|
||||
else
|
||||
vary = vary .. ',' .. v
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function nodeSwitched()
|
||||
local status = ngx.status
|
||||
if status ~= 200 and status ~= 206 then
|
||||
@ -113,7 +100,6 @@ local function nodeSwitched()
|
||||
addHdr('--switched', '1')
|
||||
|
||||
ngx.header['cache-control'] = 'no-cache'
|
||||
ngx.header['vary'] = '--url'
|
||||
ngx.var._switched = resLenStr
|
||||
ngx.ctx._switched = true
|
||||
|
||||
@ -147,9 +133,6 @@ for k, v in pairs(h) do
|
||||
end
|
||||
ngx.header[k] = nil
|
||||
|
||||
elseif k == 'vary' then
|
||||
addVary(v)
|
||||
|
||||
elseif detail and
|
||||
-- 非简单头无法被 fetch 读取,需添加到 aceh 列表 --
|
||||
-- https://developer.mozilla.org/en-US/docs/Glossary/Simple_response_header
|
||||
@ -164,4 +147,9 @@ for k, v in pairs(h) do
|
||||
end
|
||||
end
|
||||
|
||||
-- 不缓存非 GET 请求
|
||||
if ngx.req.get_method() ~= 'GET' then
|
||||
ngx.header['cache-control'] = 'no-cache'
|
||||
end
|
||||
|
||||
flushHdr()
|
Loading…
Reference in New Issue
Block a user