about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2025-03-28 17:33:30 +0100
committerbptato <nincsnevem662@gmail.com>2025-03-28 17:33:30 +0100
commit470e32e3b056d2226967aed0fa8cdb24cebd9401 (patch)
treed32b4120da31ccea7501b9950a48db0141a7ed50 /src
parente42565a5a9243d09beec9b89491e50d7032b294c (diff)
downloadchawan-470e32e3b056d2226967aed0fa8cdb24cebd9401.tar.gz
loader: respect credentials mode
Diffstat (limited to 'src')
-rw-r--r--src/html/script.nim4
-rw-r--r--src/html/xmlhttprequest.nim7
-rw-r--r--src/server/loader.nim21
-rw-r--r--src/server/request.nim22
4 files changed, 37 insertions, 17 deletions
diff --git a/src/html/script.nim b/src/html/script.nim
index 568c072f..07bbcaa7 100644
--- a/src/html/script.nim
+++ b/src/html/script.nim
@@ -90,6 +90,7 @@ type
 # Forward declaration hack
 # set in html/dom
 var errorImpl*: proc(ctx: JSContext; ss: varargs[string]) {.nimcall.}
+var getEnvSettingsImpl*: proc(ctx: JSContext): EnvironmentSettings {.nimcall.}
 
 proc find*(moduleMap: ModuleMap; url: URL; moduleType: string): int =
   let surl = $url
@@ -194,3 +195,6 @@ proc identity(ctx: JSContext; this_val: JSValueConst; argc: cint;
 #TODO move to javascript.nim?
 proc identityFunction*(ctx: JSContext; val: JSValueConst): JSValue =
   return JS_NewCFunctionData(ctx, identity, 0, 0, 1, val.toJSValueArray())
+
+proc getEnvSettings*(ctx: JSContext): EnvironmentSettings =
+  return ctx.getEnvSettingsImpl()
diff --git a/src/html/xmlhttprequest.nim b/src/html/xmlhttprequest.nim
index e48b858c..0d0c49f6 100644
--- a/src/html/xmlhttprequest.nim
+++ b/src/html/xmlhttprequest.nim
@@ -288,7 +288,9 @@ proc send(ctx: JSContext; this: XMLHttpRequest; body: JSValueConst = JS_NULL):
   var body = body
   if this.requestMethod in {hmGet, hmHead}:
     body = JS_NULL
-  let request = newRequest(this.requestURL, this.requestMethod, this.headers)
+  let credentialsMode = if this.withCredentials: cmInclude else: cmSameOrigin
+  let request = newRequest(this.requestURL, this.requestMethod, this.headers,
+    credentialsMode = credentialsMode)
   if not JS_IsNull(body):
     var document: Document = nil
     if ctx.fromJS(body, document).isSome:
@@ -304,8 +306,7 @@ proc send(ctx: JSContext; this: XMLHttpRequest; body: JSValueConst = JS_NULL):
   let jsRequest = JSRequest(
     #TODO unsafe request flag, client, use-url-credentials, initiator type
     request: request,
-    mode: rmCors,
-    credentialsMode: if this.withCredentials: cmInclude else: cmSameOrigin,
+    mode: rmCors
   )
   if JS_IsNull(body):
     this.flags.incl(xhrfUploadComplete)
diff --git a/src/server/loader.nim b/src/server/loader.nim
index 802a2b5b..6f9d881f 100644
--- a/src/server/loader.nim
+++ b/src/server/loader.nim
@@ -31,6 +31,7 @@ import std/times
 
 import config/cookie
 import config/urimethodmap
+import html/script
 import io/dynstream
 import io/packetreader
 import io/packetwriter
@@ -776,9 +777,19 @@ proc findItem(authMap: seq[AuthItem]; origin: Origin): AuthItem =
       return it
   return nil
 
-proc findAuth(client: ClientHandle; url: URL): AuthItem =
-  if client.authMap.len > 0:
-    return client.authMap.findItem(url.authOrigin)
+proc includeCredentials(config: LoaderClientConfig; request: Request; url: URL;
+    header: string): bool =
+  if header in request.headers:
+    return false
+  return request.credentialsMode == cmInclude or
+    request.credentialsMode == cmSameOrigin and
+      config.originURL == nil or
+        url.origin.isSameOrigin(config.originURL.origin)
+
+proc findAuth(client: ClientHandle; request: Request; url: URL): AuthItem =
+  if client.config.includeCredentials(request, url, "Authorization"):
+    if client.authMap.len > 0:
+      return client.authMap.findItem(url.authOrigin)
   return nil
 
 proc putMappedURL(s: var seq[tuple[name, value: string]]; url: URL;
@@ -937,7 +948,7 @@ proc loadCGI(ctx: var LoaderContext; client: ClientHandle; handle: InputHandle;
     istream = newPosixStream(pipefdRead[0])
     ostream = newPosixStream(pipefdRead[1])
   let contentLen = request.body.contentLength()
-  let auth = if prevURL != nil: client.findAuth(prevURL) else: nil
+  let auth = if prevURL != nil: client.findAuth(request, prevURL) else: nil
   let env = setupEnv(cpath, request, contentLen, prevURL, config, auth)
   var pid: int
   try:
@@ -1313,7 +1324,7 @@ proc setupRequestDefaults(request: Request; config: LoaderClientConfig) =
     if k notin request.headers:
       request.headers[k] = v
   if config.cookieJar != nil and config.cookieJar.cookies.len > 0:
-    if "Cookie" notin request.headers:
+    if config.includeCredentials(request, request.url, "Cookie"):
       let cookie = config.cookieJar.serialize(request.url)
       if cookie != "":
         request.headers["Cookie"] = cookie
diff --git a/src/server/request.nim b/src/server/request.nim
index 31b4c117..e129be9f 100644
--- a/src/server/request.nim
+++ b/src/server/request.nim
@@ -81,12 +81,12 @@ type
     body*: RequestBody
     referrer*: URL
     tocache*: bool
+    credentialsMode*: CredentialsMode
 
   JSRequest* = ref object
     request*: Request
     mode* {.jsget.}: RequestMode
     destination* {.jsget.}: RequestDestination
-    credentialsMode* {.jsget.}: CredentialsMode
     origin*: RequestOrigin
     window*: RequestWindow
     client*: Option[EnvironmentSettings]
@@ -130,6 +130,9 @@ func url(this: JSRequest): URL =
 proc jsUrl(this: JSRequest): string {.jsfget: "url".} =
   return $this.url
 
+func credentialsMode(this: JSRequest): string {.jsfget.} =
+  return $this.request.credentialsMode
+
 #TODO pretty sure this is incorrect
 proc jsReferrer(this: JSRequest): string {.jsfget: "referrer".} =
   if this.request.referrer != nil:
@@ -137,14 +140,16 @@ proc jsReferrer(this: JSRequest): string {.jsfget: "referrer".} =
   return ""
 
 func newRequest*(url: URL; httpMethod = hmGet; headers = newHeaders(hgRequest);
-    body = RequestBody(); referrer: URL = nil; tocache = false): Request =
+    body = RequestBody(); referrer: URL = nil; tocache = false;
+    credentialsMode = cmSameOrigin): Request =
   return Request(
     url: url,
     httpMethod: httpMethod,
     headers: headers,
     body: body,
     referrer: referrer,
-    tocache: tocache
+    tocache: tocache,
+    credentialsMode: credentialsMode
   )
 
 func createPotentialCORSRequest*(url: URL; destination: RequestDestination;
@@ -157,10 +162,9 @@ func createPotentialCORSRequest*(url: URL; destination: RequestDestination;
     mode = rmSameOrigin
   let credentialsMode = if cors == caAnonymous: cmSameOrigin else: cmInclude
   return JSRequest(
-    request: newRequest(url),
+    request: newRequest(url, credentialsMode = credentialsMode),
     destination: destination,
-    mode: mode,
-    credentialsMode: credentialsMode
+    mode: mode
   )
 
 type
@@ -223,7 +227,7 @@ proc newRequest*(ctx: JSContext; resource: JSValueConst;
     httpMethod = res.request.httpMethod
     headers[] = res.headers[]
     referrer = res.request.referrer
-    credentials = res.credentialsMode
+    credentials = res.request.credentialsMode
     body = res.request.body
     fallbackMode = opt(RequestMode)
     window = res.window
@@ -270,10 +274,10 @@ proc newRequest*(ctx: JSContext; resource: JSValueConst;
       httpMethod,
       headers,
       body,
-      referrer = referrer
+      referrer = referrer,
+      credentialsMode = credentials
     ),
     mode: mode,
-    credentialsMode: credentials,
     destination: destination,
     window: window
   ))