@@ -3062,6 +3062,54 @@ bool get_header_value_for_name(JSContext *cx, HandleObject self, HandleValue nam
3062
3062
return true ;
3063
3063
}
3064
3064
3065
+ std::string_view special_chars = " =,;" ;
3066
+
3067
+ std::vector<std::string_view> splitCookiesString (std::string_view cookiesString) {
3068
+ std::vector<std::string_view> cookiesStrings;
3069
+ std::size_t currentPosition = 0 ; // Current position in the string
3070
+ std::size_t start; // Start position of the current cookie
3071
+ char currentChar; // Current character in the string
3072
+ std::size_t lastComma; // Position of the last comma found
3073
+ std::size_t nextStart; // Position of the start of the next cookie
3074
+
3075
+ // Iterate over the string and split it into cookies.
3076
+ while (currentPosition < cookiesString.length ()) {
3077
+ start = currentPosition;
3078
+
3079
+ // Iterate until we find a comma that might be used as a separator.
3080
+ while ((currentPosition = cookiesString.find_first_of (" ," , currentPosition)) !=
3081
+ std::string_view::npos) {
3082
+ currentChar = cookiesString.at (currentPosition);
3083
+ // ',' is a cookie separator only if we later have '=', before having ';' or ','
3084
+ lastComma = currentPosition;
3085
+ nextStart = ++currentPosition;
3086
+
3087
+ // Check if the next sequence of characters is a non-special character followed by an equals
3088
+ // sign.
3089
+ currentPosition = cookiesString.find_first_of (special_chars, currentPosition);
3090
+
3091
+ // If the current character is an equals sign, we have found a cookie separator.
3092
+ if (currentPosition != std::string_view::npos && cookiesString.at (currentPosition) == ' =' ) {
3093
+ // currentPosition is inside the next cookie, so back up and return it.
3094
+ currentPosition = nextStart;
3095
+ cookiesStrings.push_back (cookiesString.substr (start, lastComma - start));
3096
+ start = currentPosition;
3097
+ } else {
3098
+ // The cookie contains ';' or ',' as part of the value
3099
+ // so we need to keep accumulating characters
3100
+ currentPosition = lastComma + 1 ;
3101
+ }
3102
+ }
3103
+
3104
+ // If we reach the end of the string without finding a separator, add the last cookie to the
3105
+ // vector.
3106
+ if (currentPosition >= cookiesString.length ()) {
3107
+ cookiesStrings.push_back (cookiesString.substr (start, cookiesString.length () - start));
3108
+ }
3109
+ }
3110
+ return cookiesStrings;
3111
+ }
3112
+
3065
3113
static bool ensure_all_header_values_from_handle (JSContext *cx, HandleObject self,
3066
3114
HandleObject backing_map) {
3067
3115
if (!lazy_values (self))
@@ -3108,19 +3156,33 @@ bool append_header_value(JSContext *cx, HandleObject self, HandleValue name, Han
3108
3156
3109
3157
// Ensure that any host-side values have been applied JS-side.
3110
3158
RootedValue v (cx);
3111
- if (!ensure_value_for_header (cx, self, normalized_name, &v))
3159
+ if (!ensure_value_for_header (cx, self, normalized_name, &v)) {
3112
3160
return false ;
3161
+ }
3113
3162
3114
3163
Mode mode = detail::mode (self);
3115
3164
if (mode != Mode::Standalone) {
3116
3165
AppendHeaderOperation *op;
3117
- if (mode == Mode::ProxyToRequest)
3166
+ if (mode == Mode::ProxyToRequest) {
3118
3167
op = (AppendHeaderOperation *)xqd_req_header_append;
3119
- else
3168
+ } else {
3120
3169
op = (AppendHeaderOperation *)xqd_resp_header_append;
3121
- if (!HANDLE_RESULT (
3122
- cx, op (handle (self), name_chars.get (), name_len, value_chars.get (), value_len))) {
3123
- return false ;
3170
+ }
3171
+ std::string_view name (name_chars.get (), name_len);
3172
+ if (name == " set-cookie" ) {
3173
+ std::string_view value (value_chars.get (), value_len);
3174
+ auto values = splitCookiesString (value);
3175
+ for (auto value : values) {
3176
+ auto result = op (handle (self), name_chars.get (), name_len, value.data (), value.length ());
3177
+ if (!HANDLE_RESULT (cx, result)) {
3178
+ return false ;
3179
+ }
3180
+ }
3181
+ } else {
3182
+ auto result = op (handle (self), name_chars.get (), name_len, value_chars.get (), value_len);
3183
+ if (!HANDLE_RESULT (cx, result)) {
3184
+ return false ;
3185
+ }
3124
3186
}
3125
3187
}
3126
3188
0 commit comments