From a461d18ec823c13499a9ff4a5a64290f60693f73 Mon Sep 17 00:00:00 2001 From: Ivan Vandot Date: Tue, 5 Dec 2023 22:47:51 +0100 Subject: [PATCH] add support for access from iPhone in local net --- lodev.nimble | 4 ++-- src/lodev.nim | 38 +++++++++++++++++++++++++------------- src/lodev/httpserver.nim | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 src/lodev/httpserver.nim diff --git a/lodev.nimble b/lodev.nimble index 4fe569a..1f6aed4 100644 --- a/lodev.nimble +++ b/lodev.nimble @@ -1,6 +1,6 @@ # Package -version = "0.1.1" +version = "0.1.3" author = "vandot" description = "Simple reverse proxy server for local development" license = "MIT" @@ -16,7 +16,7 @@ skipDirs = @[ # Dependencies requires "nim >= 1.6.6" requires "chronos" -requires "lodns" +requires "lodns >= 0.1.9" requires "locert" # Tasks diff --git a/src/lodev.nim b/src/lodev.nim index ed60959..bf4a6bc 100644 --- a/src/lodev.nim +++ b/src/lodev.nim @@ -1,13 +1,18 @@ -import std/[os, parseopt, strutils] -import pkg/lodnspkg/[actions, server] +import std/[os, parseopt, strutils, nativesockets] +when not defined macosx: + import pkg/lodnspkg/[actions, server] import pkg/locertpkg/actions as certActions import threadpool import chronos -import ./lodev/[proxy] +import ./lodev/[proxy, httpserver] -const tld = "lo" +var tld = "lo" +var domain = "dev" +when defined macosx: + tld = "local" + domain = getHostname() proc writeVersion(): string = const NimblePkgVersion {.strdefine.} = "dev" @@ -31,24 +36,28 @@ proc writeHelp() = proc main() = var start = false - dnsIp :string - dnsPort :int targetIp = "127.0.0.1" targetPort = Port(3000) + when not defined macosx: + var + dnsIp :string + dnsPort :int for kind, key, value in getOpt(): case kind of cmdArgument: case key of "install": - (dnsIp, dnsPort) = actions.systemProbe() - certActions.installCA("dev." & tld, true) - actions.install(dnsIp, dnsPort, tld) + when not defined macosx: + (dnsIp, dnsPort) = actions.systemProbe() + actions.install(dnsIp, dnsPort, domain & "." & tld) + certActions.installCA(domain & "." & tld, true) of "start": start = true of "uninstall": + when not defined macosx: + actions.uninstall(domain & "." & tld) certActions.uninstallCA(true) - actions.uninstall(tld) else: echo "unknown argument: ", key writeHelp() @@ -71,11 +80,14 @@ proc main() = discard if start: - (dnsIp, dnsPort) = actions.systemProbe() - var cert = certActions.getCert(true) + let cert = certActions.getCert(true) + let ca = os.splitPath(cert[0])[0] & "/locertCA.pem" let secureProxy = ProxyServer(targetHost: targetIp, targetPort: targetPort, serverIdent: writeVersion(), cert: cert) let proxyServer = createServer(secureProxy) - spawn server.serve(dnsIp, dnsPort, tld) + when not defined macosx: + (dnsIp, dnsPort) = actions.systemProbe() + spawn server.serve(dnsIp, dnsPort, domain & "." & tld) + spawn httpserver.serve(domain & "." & tld, ca) proxyServer.start() waitFor proxyServer.join() sync() diff --git a/src/lodev/httpserver.nim b/src/lodev/httpserver.nim new file mode 100644 index 0000000..c60beb9 --- /dev/null +++ b/src/lodev/httpserver.nim @@ -0,0 +1,32 @@ +import std/[asynchttpserver, asyncdispatch] +import std/strutils + +import helpers + +template log(lvl: string, msg: varargs[string, `$`]) = + stdout.writeLine(datetime() & lvl.toUpper() & " " & @msg) + +proc httpServer(domain: string, cert: string) {.async.} = + var server = newAsyncHttpServer() + proc cb(req: Request) {.async.} = + if req.url.path == "/ca": + let caFile = readFile(cert) + let headers = newHttpHeaders([("Content-Type","text/plain; charset=utf-8"),("Content-Disposition","attachment; filename=\"locertCA.pem\"")]) + await req.respond(Http200, caFile, headers) + else: + let headers = newHttpHeaders([("Content-Type","text/plain; charset=utf-8"),("Location","https://" & domain)]) + await req.respond(Http302, "", headers) + var address = "127.0.0.1" + when defined macosx: # https://developer.apple.com/forums/thread/674179 + address = "0.0.0.0" + server.listen(Port(80), address) + log("info", "status=listening ip=", address, " port=80") + log("info", "status=listening host=", domain) + while true: + if server.shouldAcceptRequest(): + await server.acceptRequest(cb) + else: + await sleepAsync(500) + +proc serve*(domain: string, cert: string) = + waitFor httpServer(domain, cert)