@@ -10,6 +10,7 @@ import let MacroCore.console
1010import class http. IncomingMessage
1111import class http. ServerResponse
1212
13+
1314// "Set-Cookie:" Name "=" Value *( ";" Attribute)
1415// "Cookie:" Name "=" Value *( ";" Name "=" Value)
1516//
@@ -21,11 +22,12 @@ import class http.ServerResponse
2122/// Module and object at the same time
2223///
2324/// Usage:
24- ///
25- /// let cookies = Cookies(req, res)
26- ///
27- /// cookies.set("theAnswer", "42") // set a cookie
28- /// if let answer = cookies.get("theAnswer") // get a cookie
25+ /// ```swift
26+ /// let cookies = Cookies(req, res)
27+ ///
28+ /// cookies.set("theAnswer", "42") // set a cookie
29+ /// if let answer = cookies.get("theAnswer") // get a cookie
30+ /// ```
2931///
3032public struct Cookies {
3133
@@ -37,24 +39,33 @@ public struct Cookies {
3739 self . res = res
3840
3941 // request values we care about
40- self . cookies = req. extractStringCookieDictionary ( )
42+ self . cookies = req. extractStringCookieDictionary ( )
4143 }
4244
4345
4446 // get/set funcs
4547
48+ @inlinable
4649 public func get( _ name: String ) -> String ? {
4750 return cookies [ name]
4851 }
4952
53+ @inlinable
5054 public func set( cookie c: Cookie ) {
51- guard res != nil else {
55+ guard let res = res else {
5256 console. warn ( " attempt to set cookie, but got no response object! " )
5357 return
5458 }
55- res!. setHeader ( " Set-Cookie " , c. description)
59+ res. setHeader ( " Set-Cookie " , c. httpHeaderValue)
60+ }
61+
62+ @inlinable
63+ public func set( _ cookie: Cookie ) {
64+ // TODO: convenience, deprecate one
65+ set ( cookie: cookie)
5666 }
5767
68+ @inlinable
5869 public func set( _ name: String , _ value: String ,
5970 path : String ? = " / " ,
6071 httpOnly : Bool = true ,
@@ -73,12 +84,14 @@ public struct Cookies {
7384 set ( cookie: cookie)
7485 }
7586
87+ @inlinable
7688 public func reset( _ name: String ) {
7789 set ( cookie: Cookie ( name: name, maxAge: 0 ) )
7890 }
7991
8092 // subscript
8193
94+ @inlinable
8295 public subscript( name : String ) -> String ? {
8396 set {
8497 if let newValue = newValue {
@@ -88,13 +101,12 @@ public struct Cookies {
88101 console. error ( " attempt to set nil-value cookie: \( name) , ignoring. " )
89102 }
90103 }
91- get {
92- return get ( name)
93- }
104+ get { return get ( name) }
94105 }
95106}
96107
97108extension Cookies : CustomStringConvertible {
109+
98110 public var description : String {
99111 var ms = " <Cookies: "
100112 if cookies. isEmpty {
@@ -122,13 +134,17 @@ extension Cookies: CustomStringConvertible {
122134 }
123135}
124136
137+ // Expose the type under the "cookies" name for naming compat.
125138public let cookies = Cookies . self
126139
127140// MARK: - Internals
128141
142+ // TBD(2025-08-26): The new shared Foundation might have a proper Cookie parser?
143+
129144import struct Foundation. Date
130145
131146public struct Cookie {
147+
132148 public let name : String
133149 public var value : String
134150 public var path : String ?
@@ -263,8 +279,9 @@ extension String {
263279 }
264280}
265281
282+ /// "Cookie: a=10; b=20" => [ "a=10", "b=20" ]
266283private func splitCookieFields( headerValue v: String ) -> [ String ] {
267- return v. splitAndTrim ( splitchar: 59 ) // semicolon
284+ return v. splitAndTrim ( splitchar: 59 ) // semicolon (multiple cookies in line)
268285}
269286
270287private extension IncomingMessage {
0 commit comments