Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time




  • Scriproxy is an easy-to-use scriptable reverse proxy.
  • You can write a script to select the upstream server dynamically for each request. Header values, query values, and request paths can be used.
  • You can do more than dynamically selecting the upstream server. It is also possible to rewrite header values, query values, and others.
  • Tengo language is used for writing scripts. It has go-like syntax and good standard libraries.


$ go install


$ scriproxy --help
  scriproxy [OPTIONS]

Application Options:
      --script=    The path to a tengo script for rewriting requests
      --libraries= The tengo libraries used in the script, separated by commas

Help Options:
  -h, --help       Show this help message

You can write a go-like script for rewriting HTTP requests. Request paths, header values, query values, and others can be used (and can be modified as well.) The example scripts are shown in the "Example Scripts" section below.

Tengo language is used as a backend. It has many cool built-in standard libraries, and they can be used as well. To use the standard libraries, the library names should be specified in the command line arguments. For example, if you want to use text and fmt, --libraries=text,fmt should be added to the command line arguments.

An example command to start a proxy server is as follows.

$ scriproxy --script /path/to/script.go --libraries fmt,text

Example Scripts

These example scripts may give you the idea of what is possible with Scriproxy. You can combine the below scripts and do a lot more!

For the list of available values and functions, refer to the "Notes" section.

Simple proxy

// req.url corresponds to the url to which the request is sent.
req.url.scheme = "https" = ""

// represents the host header value
// You (almost always) have to set this value
// In most cases, should be the same value as = ""

With this script, all the requests to the proxy server are routed to with the host header value of The header/query values and the request path will be kept unchanged.

Using query values

Query values can be used for selecting the upstream server.

// Retrive values from the query = req.url.query.get("host")
req.url.scheme = req.url.query.get("scheme")

// Remove the query values to tidy up

// This is (almost always) neccessary! =

With this script, requests to /foo? are routed to and requests to /foo? are routed to

Using host header values

You can use the host header value for selecting to which upstream server to connect.

// Note that you shoud specify `--libraries=text` in the command line arguments!
text := import("text")

// We are expecting to be "", "", or something like that

splitted := text.split(, ".")
l := len(splitted)

if splitted[l-2] == "secure" {
  req.url.scheme = "https" = text.join(splitted[:l-2], ".")
} else {
  req.url.scheme = "http" = text.join(splitted[:l-1], ".")
} =

With this script, requests whose host header values are set to are routed to, and requests with host header values are routed to

Using header values

You can use header values to select the upstream server.

// Note that you shoud specify `--libraries=text` in the command line arguments!
text := import("text")

// You can use "User-Agent" instead of "user-agent"
// It acts like
ua := req.header.get("user-agent")
ua = text.to_lower(ua)

if text.contains(ua, "iphone") { = ""
} else { = ""

// Overwriting the user agent header value
req.header.set("user-agent", "my-proxy")

req.url.scheme = "https" =

With this script, requests from iPhones are routed to and the other requests are routed to

req.header.set("host", "...") does not work. To rewrite host header values, you should modify instead. This is in line with the behavior of Go's http.Request.


  •, req.url.scheme, and req.url.path can be used as values and can be modified.
  • req.url.query.get("key"), req.url.query.set("key", "value") and req.url.query.del("key") functions can be used to rewrite query values.
  • req.header.get("key"), req.header.set("key", "value"), req.header.add("key", "value") and req.header.del("key") functions can be used to rewrite header values.
  • The behaviors of the values and the functions above are simillar to Go's http.Request.
  • Scriproxy can serve around a few thousand requests per second on a modern 2-core machine.
  • By default, port 80 is used for listening. You can change it by setting PORT environment variable.


Scriproxy has built-in logging. The example log is as follows. Note that, in production, one log entry is printed without line breaks.

  "level": "info",
  "ts": 1568759341.6854603,
  "caller": "scriproxy/server.go:101",
  "msg": "received_response",
  "method": "GET",
  "remote_addr": "",
  "original_user_agent": "curl/7.58.0",
  "original_host": "localhost:8080",
  "original_url_path": "/foo",
  "original_url_query": "",
  "host": "",
  "url_scheme": "https",
  "url_host": "",
  "url_path": "/foo",
  "url_query": "",
  "status_code": 404,
  "elapsed": 0.109501097

The above log was obtained by the following commands.

$ cat > /tmp/script <<EOF = req.url.query.get("host")
req.url.scheme = req.url.query.get("scheme")
req.url.query.del("scheme") =
$ PORT=8080 scriproxy --script=/tmp/script
$ curl 'http://localhost:8080/foo?'


Easy-to-use dynamic(scriptable) reverse proxy server








No releases published


No packages published