79 lines
2.2 KiB
Nim
79 lines
2.2 KiB
Nim
import std/[asyncdispatch, base64, options, nativesockets, sequtils, strutils]
|
|
import chronicles, httpbeast, webby
|
|
import consts
|
|
|
|
template redirect(location: string): untyped =
|
|
req.send(redirCode, "", headers="Location: " & location)
|
|
|
|
func nonEmpty(path: seq[string]): seq[string] =
|
|
path.filterIt(it.len > 0)
|
|
|
|
func sanitize(input: string): string =
|
|
## Removes CRLF
|
|
for c in input:
|
|
if c != '\r' and c != '\n':
|
|
result.add c
|
|
|
|
func getHttpCode(query: QueryParams): HttpCode =
|
|
if "code" notin query: return defaultRedirectCode
|
|
return case query["code"]
|
|
of "301": Http301
|
|
of "302": Http302
|
|
of "303": Http303
|
|
of "304": Http304
|
|
of "305": Http305
|
|
of "307": Http307
|
|
of "308": Http308
|
|
else: defaultRedirectCode
|
|
|
|
proc onRequest(req: Request): Future[void] =
|
|
logScope:
|
|
path = get req.path
|
|
httpMethod = get req.httpMethod
|
|
ip = req.ip
|
|
headers = get req.headers
|
|
info "handling request"
|
|
|
|
let
|
|
rawPath = get req.path
|
|
uri = parseUrl rawPath
|
|
reqPath = rawPath.split("?")[0].split("/").nonEmpty
|
|
redirCode = getHttpCode uri.query
|
|
|
|
if reqPath.len == 0 and "url" notin uri.query:
|
|
req.send index
|
|
return
|
|
|
|
case reqPath[0]
|
|
of "base64":
|
|
if "url" notin uri.query:
|
|
req.send Http400, "required param `url` missing"
|
|
return
|
|
try:
|
|
redirect uri.query["url"].decode.sanitize
|
|
except:
|
|
req.send Http400, "invalid base64 data"
|
|
of "metadata": redirect "http://169.254.169.254/latest/meta-data/"
|
|
of "metadata6": redirect "http://[fd00:ec2::254]/latest/meta-data/"
|
|
of "localhost": redirect "http://127.0.0.1"
|
|
of "localhost6": redirect "http://[::1]"
|
|
of "zeroes": redirect "http://0.0.0.0"
|
|
of "passwd": redirect "file:///etc/passwd"
|
|
of "services": redirect "file:///etc/services"
|
|
of "env": redirect "file:///proc/self/environ"
|
|
else:
|
|
if "url" in uri.query: redirect uri.query["url"].sanitize
|
|
else: redirect rawPath[1..^1].sanitize
|
|
|
|
proc redir(port = 8081, bindAddr = "127.0.0.1", ipv6 = false): int =
|
|
## open redirector
|
|
onRequest.run initSettings(
|
|
port = Port(port),
|
|
bindAddr = bindAddr,
|
|
domain =
|
|
if ipv6: Domain.AF_INET6
|
|
else: Domain.AF_INET
|
|
)
|
|
|
|
when isMainModule:
|
|
import cligen; dispatch redir
|