diff options
author | bptato <nincsnevem662@gmail.com> | 2023-07-04 12:25:40 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-07-04 12:25:56 +0200 |
commit | b96d8cc51a7f469eaa5804c24a8b45cc4d5b3756 (patch) | |
tree | 0d1deb5281e233d6627a4cfde91732c34adbbc05 | |
parent | e961b086d263022c3486a4742d1ab29331212c62 (diff) | |
download | chawan-b96d8cc51a7f469eaa5804c24a8b45cc4d5b3756.tar.gz |
Add proxy support
-rw-r--r-- | doc/config.md | 13 | ||||
-rw-r--r-- | src/config/config.nim | 24 | ||||
-rw-r--r-- | src/display/client.nim | 6 | ||||
-rw-r--r-- | src/display/pager.nim | 41 | ||||
-rw-r--r-- | src/io/loader.nim | 6 | ||||
-rw-r--r-- | src/ips/forkserver.nim | 12 | ||||
-rw-r--r-- | todo | 1 |
7 files changed, 77 insertions, 26 deletions
diff --git a/doc/config.md b/doc/config.md index 2316ff6e..6662d1be 100644 --- a/doc/config.md +++ b/doc/config.md @@ -184,6 +184,13 @@ Network options are to be placed in the `[network]` section. https (e.g. wikipedia.org as https://wikipedia.org.)</td> </tr> +<tr> +<td>proxy</td> +<td>URL</td> +<td>Specify a proxy for all network requests Chawan makes. All proxies +supported by cURL may be used. Can be overridden by siteconf.</td> +</tr> + </table> ## Display @@ -433,6 +440,12 @@ siteconfs) are not overridden. (In other words, they will be concatenated with this stylesheet to get the final user stylesheet.)</td> </tr> +<tr> +<td>proxy</td> +<td>URL</td> +<td>Specify a proxy for network requests fetching contents of this buffer.</td> +</tr> + </table> diff --git a/src/config/config.nim b/src/config/config.nim index 1bfacd28..b546ce3c 100644 --- a/src/config/config.nim +++ b/src/config/config.nim @@ -37,6 +37,7 @@ type document_charset: seq[Charset] images: Opt[bool] stylesheet: Opt[string] + proxy: Opt[string] StaticOmniRule = object match: string @@ -54,6 +55,7 @@ type document_charset*: seq[Charset] images*: Opt[bool] stylesheet*: Opt[string] + proxy*: Opt[URL] OmniRule* = object match*: Regex @@ -81,6 +83,7 @@ type NetworkConfig = object max_redirect*: int32 prepend_https*: bool + proxy*: Opt[string] DisplayConfig = object color_mode*: Opt[ColorMode] @@ -120,6 +123,7 @@ type scripting*: bool charsets*: seq[Charset] images*: bool + proxy*: URL ForkServerConfig* = object tmpdir*: string @@ -141,9 +145,19 @@ func getForkServerConfig*(config: Config): ForkServerConfig = ambiguous_double: config.display.double_width_ambiguous ) +func getProxy*(config: Config): URL = + if config.network.proxy.isSome: + let s = config.network.proxy.get + let x = parseURL(s) + if x.isSome: + return x.get + else: + raise newException(Defect, "Invalid proxy URL: " & s) + return nil + proc getBufferConfig*(config: Config, location: URL, cookiejar: CookieJar, headers: Headers, referer_from, scripting: bool, charsets: seq[Charset], - images: bool, userstyle: string): BufferConfig = + images: bool, userstyle: string, proxy: URL): BufferConfig = result = BufferConfig( userstyle: userstyle, filter: newURLFilter(scheme = some(location.scheme), default = true), @@ -152,7 +166,8 @@ proc getBufferConfig*(config: Config, location: URL, cookiejar: CookieJar, referer_from: referer_from, scripting: scripting, charsets: charsets, - images: images + images: images, + proxy: proxy ) new(result.headers) result.headers[] = DefaultHeaders @@ -177,6 +192,11 @@ proc getSiteConfig*(config: Config, jsctx: JSContext): seq[SiteConfig] = let fun = jsctx.eval(sc.rewrite_url.get, "<siteconf>", JS_EVAL_TYPE_GLOBAL) conf.rewrite_url = getJSFunction[URL, URL](jsctx, fun) + if sc.proxy.isSome: + let x = parseURL(sc.proxy.get) + if x.isNone: + raise newException(Defect, "invalid URL: " & sc.proxy.get) + conf.proxy = opt(x.get) result.add(conf) proc getOmniRules*(config: Config, jsctx: JSContext): seq[OmniRule] = diff --git a/src/display/client.nim b/src/display/client.nim index 5134f130..f7e89b78 100644 --- a/src/display/client.nim +++ b/src/display/client.nim @@ -566,7 +566,11 @@ proc newClient*(config: Config, dispatcher: Dispatcher): Client = result.config = config result.dispatcher = dispatcher result.attrs = getWindowAttributes(stdout) - result.loader = dispatcher.forkserver.newFileLoader() + let forkserver = dispatcher.forkserver + result.loader = forkserver.newFileLoader( + proxy = config.getProxy(), + acceptProxy = true + ) result.jsrt = newJSRuntime() result.jsrt.setInterruptHandler(interruptHandler, cast[pointer](result)) JS_SetModuleLoaderFunc(result.jsrt, normalizeModuleName, clientLoadJSModule, diff --git a/src/display/pager.nim b/src/display/pager.nim index c8d0b83e..2698550c 100644 --- a/src/display/pager.nim +++ b/src/display/pager.nim @@ -39,34 +39,35 @@ type SEARCH_B, ISEARCH_F, ISEARCH_B, GOTO_LINE Pager* = ref object + alerton: bool + alerts: seq[string] + askcursor: int askpromise*: Promise[bool] askprompt: string - askcursor: int - numload*: int - alerts: seq[string] - alerton: bool commandMode* {.jsget.}: bool + config: Config container*: Container + cookiejars: Table[string, CookieJar] dispatcher*: Dispatcher + display: FixedGrid + iregex: Result[Regex, string] lineedit*: Option[LineEdit] + linehist: array[LineMode, LineHistory] linemode*: LineMode - username: string - scommand*: string - config: Config + numload*: int + omnirules: seq[OmniRule] + procmap*: Table[Pid, Container] + proxy: URL + redraw*: bool regex: Opt[Regex] - iregex: Result[Regex, string] reverseSearch: bool + scommand*: string + siteconf: seq[SiteConfig] statusgrid*: FixedGrid + term*: Terminal tty: File - procmap*: Table[Pid, Container] unreg*: seq[(Pid, SocketStream)] - display: FixedGrid - redraw*: bool - term*: Terminal - linehist: array[LineMode, LineHistory] - siteconf: seq[SiteConfig] - omnirules: seq[OmniRule] - cookiejars: Table[string, CookieJar] + username: string jsDestructor(Pager) @@ -181,7 +182,8 @@ proc newPager*(config: Config, attrs: WindowAttributes, statusgrid: newFixedGrid(attrs.width), term: newTerminal(stdout, config, attrs), siteconf: config.getSiteConfig(ctx), - omnirules: config.getOmniRules(ctx) + omnirules: config.getOmniRules(ctx), + proxy: config.getProxy() ) return pager @@ -576,6 +578,7 @@ proc applySiteconf(pager: Pager, url: var URL): BufferConfig = var images: bool var charsets = pager.config.encoding.document_charset var userstyle = pager.config.css.stylesheet + var proxy = pager.proxy for sc in pager.siteconf: if sc.url.isSome and not sc.url.get.match($url): continue @@ -606,8 +609,10 @@ proc applySiteconf(pager: Pager, url: var URL): BufferConfig = if sc.stylesheet.isSome: userstyle &= "\n" userstyle &= sc.stylesheet.get + if sc.proxy.isSome: + proxy = sc.proxy.get return pager.config.getBufferConfig(url, cookiejar, headers, - referer_from, scripting, charsets, images, userstyle) + referer_from, scripting, charsets, images, userstyle, proxy) # Load request in a new buffer. proc gotoURL(pager: Pager, request: Request, prevurl = none(URL), diff --git a/src/io/loader.nim b/src/io/loader.nim index 6583ce2c..46f694e6 100644 --- a/src/io/loader.nim +++ b/src/io/loader.nim @@ -84,6 +84,10 @@ type filter*: URLFilter cookiejar*: CookieJar referrerpolicy*: ReferrerPolicy + proxy*: URL + # When set to false, requests with a proxy URL are overridden by the + # loader proxy. + acceptProxy*: bool FetchPromise* = Promise[Result[Response, JSError]] @@ -132,6 +136,8 @@ proc onLoad(ctx: LoaderContext, stream: Stream) = let r = getReferer(request.referer, request.url, ctx.config.referrerpolicy) if r != "": request.headers["Referer"] = r + if request.proxy == nil or not ctx.config.acceptProxy: + request.proxy = ctx.config.proxy ctx.loadResource(request, stream) proc acceptConnection(ctx: LoaderContext) = diff --git a/src/ips/forkserver.nim b/src/ips/forkserver.nim index e2e825c1..62d41198 100644 --- a/src/ips/forkserver.nim +++ b/src/ips/forkserver.nim @@ -15,6 +15,7 @@ import ips/serialize import ips/serversocket import types/buffersource import types/cookie +import types/url import utils/twtstr type @@ -33,8 +34,8 @@ type children: seq[(Pid, Pid)] proc newFileLoader*(forkserver: ForkServer, defaultHeaders: Headers = nil, - filter = newURLFilter(default = true), - cookiejar: CookieJar = nil): FileLoader = + filter = newURLFilter(default = true), cookiejar: CookieJar = nil, + proxy: URL = nil, acceptProxy = false): FileLoader = new(result) forkserver.ostream.swrite(FORK_LOADER) var defaultHeaders = defaultHeaders @@ -44,7 +45,9 @@ proc newFileLoader*(forkserver: ForkServer, defaultHeaders: Headers = nil, let config = LoaderConfig( defaultHeaders: defaultHeaders, filter: filter, - cookiejar: cookiejar + cookiejar: cookiejar, + proxy: proxy, + acceptProxy: acceptProxy ) forkserver.ostream.swrite(config) forkserver.ostream.flush() @@ -113,7 +116,8 @@ proc forkBuffer(ctx: var ForkServerContext): Pid = defaultHeaders: config.headers, filter: config.filter, cookiejar: config.cookiejar, - referrerpolicy: config.referrerpolicy + referrerpolicy: config.referrerpolicy, + proxy: config.proxy ) ) let pid = fork() diff --git a/todo b/todo index f7644770..c23e689c 100644 --- a/todo +++ b/todo @@ -50,7 +50,6 @@ network: - gopher - gemini? (not a fan, but quite a bit of interesting content is on gemini) - uBO integration? (or at least implement filter lists) -- socks/http proxies (just settings needed...) - websockets (curl supports ws) - integrate curl-impersonate (LD_PRELOAD works, but still...) external: |