การเขียนสคริปต์ JavaScript

Chute รองรับการเขียนสคริปต์ JavaScript สำหรับการแก้ไขคำขอ/การตอบกลับขั้นสูง การจับคู่กฎที่กำหนดเอง การแก้ไข DNS และงานตามกำหนดเวลา สคริปต์ใช้เอนจิน JavaScriptCore ของ Apple และทำตาม API สคริปต์ที่เข้ากันได้กับ Surge

สคริปต์ถูกกำหนดในส่วน [Script] ของไฟล์การกำหนดค่า

การกำหนดค่า

[Script]
MyScript = type=http-request, script-path=/path/to/script.js, pattern=^https?://example\.com, requires-body=true, max-size=262144, timeout=10, argument=myArg, debug=true
CronJob = type=cron, script-path=/path/to/cron.js, cron-expression=* * * * *, wake-system=true

พารามิเตอร์สคริปต์

พารามิเตอร์ จำเป็น ค่าเริ่มต้น คำอธิบาย
type ใช่ http-request ประเภททริกเกอร์สคริปต์ (ดูด้านล่าง)
script-path ใช่ เส้นทางไฟล์ในเครื่องหรือ URL HTTP(S) ไปยังสคริปต์ JS
pattern ไม่ (ตรงทั้งหมด) รูปแบบ regex URL เพื่อกรองเมื่อสคริปต์ทริกเกอร์
requires-body ไม่ ตรวจจับอัตโนมัติ บังคับให้สคริปต์รับเนื้อหาคำขอ/การตอบกลับเต็มรูปแบบ
max-size ไม่ 131072 (128KB) ขนาดเนื้อหาสูงสุดเป็นไบต์สำหรับสคริปต์ที่เข้าถึงเนื้อหา
timeout ไม่ 5.0 วินาที เวลาหมดการทำงานต่อสคริปต์
argument ไม่ อาร์กิวเมนต์สตริงที่กำหนดเอง พร้อมใช้งานเป็น $argument ใน JS
debug ไม่ false ข้ามแคชการคอมไพล์เพื่อการดีบัก
cron-expression ไม่ นิพจน์กำหนดเวลา cron (สำหรับประเภท cron เท่านั้น)
wake-system ไม่ false ปลุกระบบเพื่อดำเนินการสคริปต์ cron (เฉพาะ iOS)
enable ไม่ true เปิดหรือปิดใช้งานสคริปต์นี้
script-update-interval ไม่ 0 วินาทีระหว่างการอัปเดตสคริปต์ระยะไกล (-1 = ไม่เลย, 0 = เฉพาะเมื่อเริ่มต้น)

ประเภทสคริปต์

สตริงประเภท Enum คำอธิบาย
http-request HTTP Request ดักจับและแก้ไขคำขอ HTTP ก่อนอัปสตรีม
http-response HTTP Response ดักจับและแก้ไขการตอบกลับ HTTP ก่อนไคลเอนต์
http-request-before-send HTTP Request Before Send แก้ไขคำขอหลังจากรวบรวมเนื้อหาเต็ม ก่อนส่ง
rule Rule ตรรกะการจับคู่กฎที่กำหนดเอง
dns DNS การแก้ไข DNS ที่กำหนดเอง
cron Cron สคริปต์ตามกำหนดเวลา
event Event ตัวจัดการเหตุการณ์ระบบ (เช่น network-changed)

การตรวจจับเนื้อหาอัตโนมัติ: หากซอร์สสคริปต์มี $request.body หรือ $response.body เนื้อหาจะถูกให้โดยอัตโนมัติสูงสุด max-size ใช้ requires-body=true เพื่อบังคับพฤติกรรมนี้


การอ้างอิง API JavaScript

สคริปต์ทำงานในสภาพแวดล้อม JavaScriptCore แบบแซนด์บ็อกซ์พร้อมวัตถุส่วนกลางต่อไปนี้

$request (อ่านอย่างเดียว)

พร้อมใช้งานใน: http-request, http-response, http-request-before-send, rule

คุณสมบัติ ประเภท คำอธิบาย
.url String URL คำขอแบบเต็ม
.method String เมธอด HTTP (GET, POST ฯลฯ) หรือ QUERY สำหรับ DNS
.headers Object ส่วนหัวคำขอเป็นคู่ key-value
.body String หรือ null เนื้อหาคำขอ (ถอดรหัส UTF-8)
.hostname String ชื่อโฮสต์เป้าหมาย
.destPort Number พอร์ตปลายทาง
.processPath String เส้นทางกระบวนการที่ร้องขอ (เฉพาะ macOS)
.userAgent String ค่าส่วนหัว User-Agent
.sourceIP String ที่อยู่ IP ต้นทาง
.listenPort Number พอร์ตการฟังของพร็อกซี
.requestId String ID คำขอที่ไม่ซ้ำ
.dnsResult String ที่อยู่ IP ที่แก้ไขแล้ว
.srcPort Number พอร์ตต้นทาง
.protocol String โปรโตคอลที่ตรวจพบ: http, https, tcp, dns

$response (อ่านอย่างเดียว)

พร้อมใช้งานใน: http-response

คุณสมบัติ ประเภท คำอธิบาย
.status Number รหัสสถานะ HTTP
.headers Object ส่วนหัวการตอบกลับเป็นคู่ key-value
.body String หรือ null เนื้อหาการตอบกลับ (ถอดรหัส UTF-8)

$done(value) — ตัวจัดการการเสร็จสมบูรณ์

ต้องถูกเรียกหนึ่งครั้งอย่างแน่นอนเมื่อสิ้นสุดสคริปต์เพื่อส่งสัญญาณการเสร็จสมบูรณ์ การทำงานของสคริปต์บล็อกจนกว่า $done() จะถูกเรียกหรือหมดเวลา

$done({})                        // ส่งผ่าน — ไม่มีการแก้ไข
$done()                          // ยกเลิกการเชื่อมต่อ
$done({matched: true})           // ผลการจับคู่กฎ (เฉพาะสคริปต์กฎ)
$done({address: "1.2.3.4"})      // ผลลัพธ์ DNS (เฉพาะสคริปต์ dns)

ค่าส่งคืนของสคริปต์ HTTP Request:

$done({
    url: "https://new.example.com/path",     // เขียน URL ใหม่
    headers: {"X-Custom": "value"},           // แก้ไขส่วนหัว
    body: "new request body",                 // แก้ไขเนื้อหา
    response: {                               // ส่งคืนการตอบกลับสังเคราะห์ (ข้ามอัปสตรีม)
        status: 200,
        headers: {"Content-Type": "text/html"},
        body: "<html>Blocked</html>"
    }
})

เมื่อระบุ response คำขอจะถูกตัดตอน: Chute ส่งคืนการตอบกลับสังเคราะห์โดยตรงไปยังไคลเอนต์โดยไม่ติดต่อเซิร์ฟเวอร์อัปสตรีม สิ่งนี้มีประโยชน์สำหรับการบล็อก การจำลอง API หรือการส่งคืนเนื้อหาที่แคช

ค่าส่งคืนของสคริปต์ HTTP Response:

$done({
    status: 200,                              // แก้ไขรหัสสถานะ
    headers: {"X-Custom": "value"},           // แก้ไขส่วนหัวการตอบกลับ
    body: "new response body",                // แก้ไขเนื้อหาการตอบกลับ
    url: "https://other.example.com"          // ทริกเกอร์การเปลี่ยนเส้นทาง 302
})

เมื่อระบุ url Chute ส่งคืนการเปลี่ยนเส้นทาง 302 ไปยัง URL ที่กำหนดแทนการตอบกลับเดิม

ค่าส่งคืนของสคริปต์ DNS:

$done({address: "1.2.3.4"})                  // IP เดียว
$done({addresses: ["1.2.3.4", "5.6.7.8"]})   // หลาย IP
$done({address: "10.0.0.1", ttl: 300})       // พร้อม TTL ที่กำหนดเอง (วินาที, ค่าเริ่มต้น 60)
$done({server: "8.8.8.8"})                   // ส่งต่อไปยังเซิร์ฟเวอร์ DNS ที่ระบุ

$httpClient — ไคลเอนต์ HTTP แบบ Async

ทำคำขอ HTTP จากภายในสคริปต์ คำขอทั้งหมดถูกยกเลิกเมื่อ $done() หรือหมดเวลา

$httpClient.get(url, function(error, response, data) {
    if (error) {
        console.log("Request failed: " + error)
    } else {
        console.log("Status: " + response.status)
        console.log("Response: " + data)
    }
})

$httpClient.post(url, {headers: {...}, body: "...", timeout: 5}, callback)
$httpClient.put(url, options, callback)
$httpClient.del(url, options, callback)
$httpClient.head(url, options, callback)
$httpClient.options(url, options, callback)
$httpClient.patch(url, options, callback)

ลายเซ็น Callback: callback(error, response, data)

  • error: สตริงข้อผิดพลาดหรือ null
  • response: {status: Number, headers: Object} หรือ null
  • data: สตริงเนื้อหาการตอบกลับ UTF-8 หรือ null

$persistentStore — ที่เก็บคีย์-ค่า

ที่เก็บคีย์-ค่าแบบถาวรที่คงอยู่ข้ามการเริ่มต้นสคริปต์และกระบวนการ สนับสนุนโดย NSUserDefaults

$persistentStore.write(data, key)   // เก็บค่า
$persistentStore.read(key)          // ดึงค่า
$persistentStore.remove(key)        // ลบค่า

$notification — การแจ้งเตือนในเครื่อง

ส่งการแจ้งเตือนระบบในเครื่อง

$notification.post("Title", "Subtitle", "Notification body text")

$network — ข้อมูลเครือข่าย

ข้อมูลสถานะเครือข่ายแบบอ่านอย่างเดียว

$network.dns   // อาร์เรย์ของ IP เซิร์ฟเวอร์ DNS
$network.wifi  // {ssid: "WiFiName", bssid: "aa:bb:cc:dd:ee:ff"}

$environment — ข้อมูลรันไทม์

$environment.system     // "iOS" หรือ "macOS"
$environment.appVersion // สตริงเวอร์ชันแอป

$utils — ยูทิลิตี้

$utils.geoip("1.2.3.4")   // รหัสประเทศ (เช่น "US")
$utils.ipasn("1.2.3.4")   // หมายเลข ASN (เช่น "13335")
$utils.ungzip(data)       // คลายการบีบอัดข้อมูล gzip

$klne — API ควบคุมพร็อกซี

ควบคุมรันไทม์พร็อกซีจากสคริปต์

$klne.policyGroups                    // รับกลุ่มนโยบายทั้งหมด
$klne.selectPolicy("Group", "Proxy")  // สลับนโยบายสำหรับกลุ่ม
$klne.getActiveConnections()          // แสดงรายการการเชื่อมต่อที่ใช้งาน
$klne.closeConnection("id")           // ปิดการเชื่อมต่อ
$klne.flushDNS()                      // ล้างแคช DNS
$klne.startURLTest("Group")           // ทริกเกอร์การทดสอบ URL สำหรับกลุ่ม
$klne.reloadConfiguration()           // โหลดการกำหนดค่าทั้งหมดใหม่
$klne.setOutboundMode("rule")         // ตั้งค่าโหมด: "global", "proxy", "direct", "rule"
$klne.setHTTPCaptureEnabled(true)     // เปิด/ปิด MITM

$script — ข้อมูลเมตาสคริปต์

$script.name       // ชื่อสคริปต์จากการกำหนดค่า
$script.type       // สตริงประเภทสคริปต์
$script.startTime  // การประทับเวลา Epoch

ตัวแปรส่วนกลางต่อการทำงาน

ตัวแปรต่อไปนี้ถูกฉีดต่อการทำงานของสคริปต์และเฉพาะเจาะจงกับประเภทสคริปต์บางประเภท

$argument — อาร์กิวเมนต์สคริปต์

ค่าสตริงจากพารามิเตอร์ argument= ในการกำหนดค่าสคริปต์ พร้อมใช้งานใน: http-request, http-response, http-request-before-send, rule, dns, cron

console.log("Argument: " + $argument)

$domain — โดเมน DNS (เฉพาะสคริปต์ DNS)

ชื่อโดเมนที่กำลังถูกสอบถาม พร้อมใช้งานเฉพาะในสคริปต์ dns

var domain = $domain  // เช่น "example.com"

$cronexp — นิพจน์ Cron (เฉพาะสคริปต์ Cron)

นิพจน์กำหนดเวลา cron จากการกำหนดค่าสคริปต์ พร้อมใช้งานเฉพาะในสคริปต์ cron

console.log("Schedule: " + $cronexp)  // เช่น "*/30 * * * *"

$event — ข้อมูลเหตุการณ์ (เฉพาะสคริปต์ Event)

ข้อมูลเกี่ยวกับเหตุการณ์ที่ทริกเกอร์ ปัจจุบันรองรับเฉพาะ network-changed

console.log("Event: " + $event.name)  // "network-changed"

console — การบันทึก

console.log("Debug message")    // บันทึกละเอียด
console.warn("Warning message")  // บันทึกคำเตือน
console.error("Error message")   // บันทึกคำเตือนพร้อมคำนำหน้า [JS-ERROR]

setTimeout(fn, seconds) — ตัวจับเวลา

กำหนดเวลาฟังก์ชันให้ทำงานหลังจากดีเลย์

setTimeout(function() {
    console.log("Delayed execution")
}, 2.5)  // 2.5 วินาที

$script(subScriptPath) — ตัวโหลดสคริปต์ย่อย

โหลดและประเมินไฟล์ JavaScript อื่น

$script("/path/to/helper.js")
$script("https://example.com/remote-script.js")

// ส่งข้อมูลระหว่างสคริปต์โดยใช้ $persistentStore

รายละเอียดประเภทสคริปต์

สคริปต์ HTTP Request

ทำงานเมื่อได้รับส่วนหัวคำขอ สามารถแก้ไข URL ส่วนหัว และเนื้อหาก่อนที่คำขอจะถูกส่งต่อ

[Script]
ModifyHeaders = type=http-request, script-path=modify.js, pattern=^https://api\.example\.com

สคริปต์ HTTP Response

ทำงานเมื่อได้รับส่วนหัวการตอบกลับ สามารถแก้ไขสถานะ ส่วนหัว และเนื้อหาก่อนส่งคืนไปยังไคลเอนต์

[Script]
ModifyResponse = type=http-response, script-path=response.js, pattern=^https://api\.example\.com

สคริปต์ HTTP Request Before Send

ทำงานหลังจากรวบรวมเนื้อหาคำขอเต็มรูปแบบ ก่อนส่งไปยังอัปสตรีม มีประโยชน์สำหรับการแก้ไขเนื้อหาคำขอ POST/PUT

[Script]
BeforeSend = type=http-request-before-send, script-path=before-send.js, pattern=^https://api\.example\.com, requires-body=true

สคริปต์ Rule

การจับคู่กฎที่กำหนดเอง สคริปต์ต้องเรียก $done({matched: true}) หรือ $done({matched: false})

[Rule]
SCRIPT,MyRuleScript,DIRECT

[Script]
MyRuleScript = type=rule, script-path=rule.js

สคริปต์ DNS

การแก้ไข DNS ที่กำหนดเอง รับ $domain และส่งคืนที่อยู่ที่แก้ไขแล้ว

// dns.js
var domain = $domain
if (domain === "internal.example.com") {
    $done({address: "10.0.0.1", ttl: 300})
} else {
    $done({})  // ส่งผ่านไปยังการแก้ไข DNS ปกติ
}

สคริปต์ Cron

การทำงานตามกำหนดเวลาโดยใช้นิพจน์ cron ช่วงขั้นต่ำคือ 60 วินาที

[Script]
HourlyTask = type=cron, script-path=hourly.js, cron-expression=0 * * * *

รองรับไวยากรณ์ cron แบบย่อ (เช่น */30 * * * * สำหรับทุก 30 นาที, ค่าที่คั่นด้วยคอมมา)

สคริปต์ Event

ถูกทริกเกอร์โดยเหตุการณ์ระบบ ปัจจุบันรองรับเหตุการณ์ network-changed (ยิงเมื่อ Wi-Fi หรือเครือข่ายเซลลูลาร์เปลี่ยน)

[Script]
NetChange = type=event, script-path=network-changed.js

วัตถุ $event พร้อมใช้งาน:

$event.name  // "network-changed"

ตัวอย่างการใช้งานจริง

เปลี่ยนเส้นทางอุปกรณ์มือถือ

สคริปต์ http-request ที่เปลี่ยนเส้นทางผู้ใช้มือถือตาม User-Agent:

[Script]
MobileRedirect = type=http-request, script-path=mobile-redirect.js, pattern=^https://example\\.com
// mobile-redirect.js
var ua = $request.headers["User-Agent"] || ""
if (/Mobile|Android|iPhone/.test(ua)) {
    $done({
        response: {
            status: 302,
            headers: {"Location": "https://m.example.com" + $request.url.replace(/.*example\\.com/, "")},
            body: ""
        }
    })
} else {
    $done({})
}

บล็อกเนื้อหาในการตอบกลับ API

สคริปต์ http-response ที่ลบโฆษณาและเนื้อหาสปอนเซอร์จากการตอบกลับ JSON API:

[Script]
RemoveAds = type=http-response, script-path=remove-ads.js, pattern=^https://api\\.example\\.com/feed, requires-body=true
// remove-ads.js
var body = JSON.parse($response.body)
if (body.ads) {
    delete body.ads
}
if (body.recommendations) {
    body.recommendations = body.recommendations.filter(function(r) {
        return !r.sponsored
    })
}
$done({body: JSON.stringify(body)})

แก้ไขเนื้อหาคำขอก่อนส่ง

สคริปต์ http-request-before-send ที่ทำความสะอาดเพย์โหลด POST:

[Script]
SanitizePayload = type=http-request-before-send, script-path=sanitize.js, pattern=^https://api\\.example\\.com/submit, requires-body=true
// sanitize.js
var body = JSON.parse($request.body)
body.clientSecret = "[REDACTED]"
body.timestamp = Math.floor(Date.now() / 1000)
$done({body: JSON.stringify(body)})

กฎกำหนดเอง: การจัดเส้นทางตามเวลา

สคริปต์ rule ที่เลือกพร็อกซีที่แตกต่างกันขึ้นอยู่กับช่วงเวลาของวัน:

[Rule]
SCRIPT,TimeBasedRule,ProxyA

[Script]
TimeBasedRule = type=rule, script-path=time-rule.js
// time-rule.js
var hour = new Date().getHours()
if (hour >= 9 && hour < 18) {
    $done({matched: false})  // ส่งต่อไปยังกฎถัดไปในช่วงเวลาทำงาน
} else {
    $done({matched: true})   // ใช้ ProxyA ในช่วงนอกเวลาทำงาน
}

DNS กำหนดเองสำหรับโดเมนภายใน

สคริปต์ dns ที่แก้ไขชื่อโฮสต์ภายในเป็น IP ในเครื่อง:

[Script]
InternalDNS = type=dns, script-path=internal-dns.js
// internal-dns.js
var internalHosts = {
    "gitlab.local": "10.0.0.10",
    "registry.local": "10.0.0.11",
    "monitor.local": "10.0.0.12"
}
if (internalHosts[$domain]) {
    $done({address: internalHosts[$domain], ttl: 3600})
} else {
    $done({})  // ส่งผ่านไปยัง DNS ปกติ
}

สลับนโยบายอัตโนมัติเมื่อเปลี่ยนเครือข่าย

สคริปต์ event ที่สลับไปยังกลุ่มนโยบายแบบประหยัดเมื่อใช้เซลลูลาร์:

[Script]
NetSwitch = type=event, script-path=network-switch.js
// network-switch.js
if (!$network.wifi.ssid) {
    // ใช้เซลลูลาร์ — ใช้กลุ่มข้อมูลต่ำ
    $klne.selectPolicy("MainGroup", "LowDataProxy")
    console.log("Switched to cellular profile")
} else if ($network.wifi.ssid === "Office") {
    $klne.selectPolicy("MainGroup", "DIRECT")
    console.log("Switched to office profile")
}

ตรวจสอบสุขภาพเป็นระยะ

สคริปต์ cron ที่ตรวจสอบสุขภาพพร็อกซีทุก 30 นาที:

[Script]
HealthCheck = type=cron, script-path=health-check.js, cron-expression=*/30 * * * *
// health-check.js
$httpClient.head("https://www.google.com/generate_204", {timeout: 10},
    function(error, response, data) {
        if (error || response.status !== 204) {
            console.error("Health check failed: " + (error || "status " + response.status))
            $notification.post("Chute Alert", "Health Check", "Cannot reach Google")
        } else {
            console.log("Health check OK")
        }
    }
)
$done()

เพิ่มข้อมูลการตอบกลับ API ด้วยข้อมูลภายนอก

สคริปต์ http-response ที่เพิ่มข้อมูลผู้ใช้โดยเรียก API รอง:

[Script]
EnrichUsers = type=http-response, script-path=enrich.js, pattern=^https://api\\.example\\.com/users, requires-body=true
// enrich.js
var users = JSON.parse($response.body)
var pending = users.length
if (pending === 0) { $done({}) }

users.forEach(function(user, index) {
    $httpClient.get("https://internal-api.example.com/avatar/" + user.id,
        function(error, resp, data) {
            if (!error && resp.status === 200) {
                users[index].avatar = JSON.parse(data).url
            }
            pending--
            if (pending === 0) {
                $done({body: JSON.stringify(users)})
            }
        }
    )
})

โมเดลการทำงาน

  • สคริปต์ทั้งหมดทำงานบนคิวอนุกรมเฉพาะเพื่อความปลอดภัยของเธรด
  • การทำงานของสคริปต์แต่ละครั้งมีเวลาหมดต่อสคริปต์ หาก $done() ไม่ถูกเรียกภายในเวลาหมด สคริปต์จะถูกปฏิบัติเป็นส่งผ่าน
  • พูล JSContext (ขนาด 3) ถูกใช้เพื่อประสิทธิภาพ; คอนเท็กซ์ถูกใช้ซ้ำข้ามการทำงาน
  • การคอมไพล์สคริปต์ถูกแคชโดยค่าเริ่มต้น; ใช้ debug=true เพื่อข้ามแคช
  • บน iOS/tvOS สคริปต์อยู่ภายใต้ขีดจำกัดหน่วยความจำ 10MB; บน macOS 512MB
  • สคริปต์ระยะไกล (เส้นทาง HTTP/HTTPS) ถูกดึงเมื่อเริ่มต้นและอาจถูกดึงใหม่ที่ script-update-interval วินาที

การรวมสคริปต์โมดูล

สคริปต์ยังสามารถกำหนดในไฟล์ โมดูล (.sgmodule) ภายใต้ส่วน [Script] ```

S. Smart Rabbit LLC © All Rights Reserved            updated 2026-06-28 02:09:17

results matching ""

    No results matching ""