# Scripting > HTTP request/response, rule, event, DNS, cron scripts [← Back to index](/llms.txt) --- ## Common # Scripting: Basic *Requires Surge iOS 4 or Surge Mac 3.3.0+* ## Overview JavaScript extends Surge's capabilities. Scripts are defined in a `[Script]` section with a name and parameters. ## Script Configuration Example script definitions: ``` [Script] script1 = type=http-response,pattern=^http://www.example.com/test,script-path=test.js,max-size=16384,debug=true script2 = type=cron,cronexp="* * * * *",script-path=fired.js script3 = type=http-request,pattern=^http://httpbin.org,script-path=http-request.js,requires-body=true script4 = type=dns,script-path=dns.js,debug=true ``` ## Common Parameters - **`type`**: Script category (http-request, http-response, cron, event, dns, rule, generic) - **`script-path`**: File location (relative/absolute path or URL) - **`script-update-interval`**: URL refresh interval in seconds - **`debug`**: Reloads from filesystem each execution; logs appear in request notes - **`timeout`**: Maximum execution time (default: 5s) - **`argument`**: Accessible via `$argument` - **`engine`**: JavaScript engine selection (see below) ## HTTP Request/Response Parameters - **`pattern`**: URL regex pattern matching - **`requires-body`**: Enable body modification (default: false) - **`max-size`**: Maximum body size in bytes (default: 131072) - **`binary-body-mode`**: Passes raw binary data as Uint8Array (iOS 15+, macOS+) ## Constraints & Performance Scripts support asynchronous operations. Call `$done(value)` to signal completion, even when results aren't required. Omitting this triggers timeout warnings. Performance is optimized; the JavaScript engine is efficient and shouldn't impact overall operation. ## Public API ### Environment Information - **`$network`**: Network environment details - **`$script.name`**, **`$script.startTime`**, **`$script.type`**: Current script metadata - **`$environment`**: System info (OS, build, version, language, device model) ### Data Persistence - **`$persistentStore.write(data, [key])`**: Save string data permanently - **`$persistentStore.read([key])`**: Retrieve saved data Scripts sharing a path automatically share storage. ### Control & HTTP Requests - **`$httpAPI(method, path, body, callback)`**: Call Surge's HTTP APIs - **`$httpClient.post/get/put/delete/head/options/patch(URL|options, callback)`**: HTTP requests with options for timeout, certificate verification, cookies, and redirects ### Utilities - **`console.log(message)`**: Log to Surge file - **`setTimeout(function, [delay])`**: Browser-like timer - **`$utils.geoip/ipasn/ipaso(ip)`**: IP lookup functions - **`$utils.ungzip(binary)`**: Decompress gzip data - **`$notification.post(title, subtitle, body, [options])`**: Send notifications with actions, media, and auto-dismiss ### Manual Triggering Long-press scripts in Surge iOS or use Shortcuts app. Shortcuts can pass parameters via `$intent.parameter`. ## JavaScript Engine Selection Two engines available (iOS 5.9.0+, Mac 5.5.0+): ### JavaScriptCore (JSC) - **Pros**: Fast initialization, low call overhead - **Cons**: Increases NE process memory; can trigger system termination ### WebView - **Pros**: Separate process isolation; JIT compilation for complex scripts; WebAPI support - **Cons**: Slightly higher initialization overhead; less efficient for large data transfers ### Recommendations Use JSC for small, frequently-called simple scripts (rule, DNS). Use WebView for complex or memory-intensive scripts (large JSON parsing). Add `engine=auto|jsc|webview` to configuration. Default is `auto` (prefers WebView when available). ### Availability - iOS: Both engines - macOS 10.15 and below: JSC only - macOS 11.0+: Both engines - tvOS: JSC only ## Cron # Cron ## Overview The cron function executes scripts at specified times using cron expressions. A cron expression is a string with five or six fields that define scheduling details. ## Cron Expression Format Common cron expression examples: - **Daily at 2 AM:** `0 2 *` - **Daily at 5 AM and 5 PM:** `0 5,17 *` - **Every minute:** `*` - **Every Sunday at 5 PM:** `0 17 sun` - **Every 10 minutes:** `*/10 * *` ## Implementation Scripts receive one parameter: `$cronexp`, which contains the cron expression string. Invoke `$done()` to complete execution. ## Example ```javascript // cron "0 2 * * *" script-path=cron.js $surge.setSelectGroupPolicy('Group', 'Proxy'); $done(); ``` This schedules a script to run daily at 2 AM, which sets a policy group selection and then completes. ## Available API - **`$cronexp`** — The cron expression string that triggered the script ## Dns # DNS Scripting Documentation ## Overview The `dns` function allows you to use a custom script as a DNS resolver in Surge. ## Usage Syntax ``` dns dnspod script-path=dnspod.js ``` Then add entries in the `[Host]` section: ``` [Host] example.com = script:dnspod *.example.com = script:dnspod ``` ## Script Parameters and Return Values The script receives `$domain` as the incoming parameter. The script must return one of the following: - `address`: A valid IPv4/IPv6 address as the result - `addresses`: Multiple IP addresses for the result - `server`: Instructs Surge to query a specified upstream DNS server - `servers`: Instructs Surge to query multiple upstream DNS servers When returning address or addresses, you can optionally include a `ttl` parameter (in seconds) to cache the result and prevent repeated lookups. ## Example Here's an implementation using DNSPod's public HTTP DNS API: ```javascript $httpClient.get('http://119.29.29.29/d?dn=' + $domain, function(error, response, data){ if (error) { $done({}); // Fallback to standard DNS query } else { $done({addresses: data.split(';'), ttl: 600}); } }); ``` ## Event # Event ## Overview The `event` directive evaluates a script when a specified event occurs. Currently, only one event type is supported. Scripts must invoke `$done()` to complete execution. ## Event Types ### network-changed Triggered when the system network changes. Example implementation: ```javascript // network-changed = script-path=network-changed.js,type=event,event-name=network-changed $notification.post('DNS Update', $network.dns.join(', ')); $done(); ``` This event fires whenever network conditions change on the system, allowing scripts to respond with notifications or other logic. ### notification Triggered when Surge shows a notification. The script can still get the message even if the notification's category is off. Example implementation: ```javascript // notification = script-path=notification.js,type=event,event-name=notification console.log($event.data); $done(); ``` This event enables scripts to intercept and process notifications generated by Surge, regardless of notification settings. ## Http request # HTTP Request ## Overview The `http-request` script allows modification of HTTP requests using regular expressions to match request URLs. ## Request Parameters The `$request` object contains: - **`$request.url`** (String): The request URL - **`$request.method`** (String): HTTP method - **`$request.headers`** (Object): HTTP headers - **`$request.body`** (String or Uint8Array): Request body (only with `requires-body = true`) - **`$request.id`** (String): Unique identifier for script continuity ## Response Object Scripts must invoke `$done()` with an object potentially containing: - **`url`** (String): Replacement URL (note: doesn't auto-update the Host header) - **`headers`** (Object): Replacement headers (some fields like Content-Length may be restricted) - **`body`** (String or Uint8Array): Replacement body (requires-body must be true) - **`response`** (Object): Returns an HTTP response without network operation: - `status` (Number): HTTP status code (default: 200) - `headers` (Object): Response headers - `body` (String or Uint8Array): Response body You may call `$done()` to abort or `$done({})` to leave the request unchanged. ## Example ```javascript let headers = $request.headers; headers['X-Modified-By'] = 'Surge'; $done({headers}); ``` ## Limitations - Request body cannot be overwritten with chunked encoding - Request body cannot be overwritten when 'Expect: 100-continue' header is present ## Http response # HTTP Response ## Overview The `http-response` script functionality allows modification of HTTP responses by matching request URLs with regular expressions. ## Available Parameters ### Request Object (`$request`) - `$request.url` (String): The request URL - `$request.method` (String): HTTP method used - `$request.id` (String): Unique identifier for script continuity - `$request.headers` (Object): Request HTTP headers ### Response Object (`$response`) - `$response.status` (Number): HTTP status code - `$response.headers` (Object): Response HTTP headers - `$response.body` (String or Uint8Array): Response body (UTF-8 decoded by default unless binary-mode is enabled; only available when `requires-body = true`) ## Response Modifications The `$done()` callback accepts an object with optional properties: - `body` (String or Uint8Array): Replace the response body (requires `requires-body = true`) - `headers` (Object): Replace all response headers (note: certain fields like 'Content-Length' cannot be modified) - `status` (Number): Replace the HTTP status code You may call `$done()` without arguments to abort, or `$done({})` to leave the response unchanged. ## Example ```javascript let headers = $response.headers; headers['X-Modified-By'] = 'Surge'; $done({headers}); ``` This example adds a custom header to all matching responses. ## Rule # Rule Scripting Documentation ## Overview Script-based rules allow dynamic matching logic using JavaScript. A script returns an object indicating whether a request matches the rule criteria. ## Basic Usage Define a script rule in your configuration: ``` rule ssid-rule script-path=ssid-rule.js ``` Then reference it in the `[Rule]` section: ``` SCRIPT,ssid-rule,DIRECT ``` ## Available Request Properties Scripts receive a `$request` object containing: - `hostname` (String) - `destPort` (Number) - `processPath` (String) - `userAgent` (String) - `url` (String) - `sourceIP` (String) - `listenPort` (Number) - `dnsResult` (Object) - `srcPort` (Number) - iOS 5.8.4+, Mac 5.4.4+ - `protocol` (Number) - iOS 5.8.4+, Mac 5.4.4+ ## DNS Resolution By default, SCRIPT rules skip DNS lookups. Enable resolution with the `requires-resolve` option: ``` SCRIPT,ssid-rule,DIRECT,requires-resolve ``` The DNS results appear in `$request.dnsResult`. ## Example Implementation ```javascript var hostnameMatched = ($request.hostname === 'home.com'); var ssidMatched = ($network.wifi.ssid === 'My Home'); $done({matched: (hostnameMatched && ssidMatched)}); ``` The script must return an object with a `matched` boolean property indicating the rule's result.