@@ -73,10 +73,10 @@ internal fun corsCheckOrigins(
7373 }
7474 } else {
7575 when {
76- allowsAnyHost ->
77- LOGGER .trace { " ${request.id()} : Any * host is allowed" }
76+ allowsAnyHost -> LOGGER .trace { " ${request.id()} : Any * host is allowed" }
7877 normalizedOrigin in hostsNormalized ->
7978 LOGGER .trace { " ${request.id()} : Origin $normalizedOrigin is allowed from $hostsNormalized " }
79+
8080 matchWildcardHosts ->
8181 LOGGER .trace {
8282 val (prefix, suffix) = hostsWithWildcard
@@ -85,6 +85,7 @@ internal fun corsCheckOrigins(
8585 }!!
8686 " ${request.id()} : Origin $normalizedOrigin matches wildcard host $prefix *$suffix "
8787 }
88+
8889 originPredicates.any { it(origin) } -> {
8990 LOGGER .trace {
9091 " ${request.id()} : Origin $normalizedOrigin fulfills " +
@@ -134,6 +135,27 @@ internal suspend fun ApplicationCall.respondCorsFailed() {
134135 respond(HttpStatusCode .Forbidden )
135136}
136137
138+ private fun findPortDigitStartIndex (origin : String , hostStartIndex : Int ): Int {
139+ val isIpv6 = hostStartIndex < origin.length && origin[hostStartIndex] == ' ['
140+ if (isIpv6) {
141+ val ipv6LiteralEndIndex = origin.indexOf(' ]' , hostStartIndex)
142+ if (ipv6LiteralEndIndex == - 1 ) {
143+ return - 1
144+ }
145+ val portSeparatorIndex = origin.indexOf(' :' , ipv6LiteralEndIndex)
146+ return if (portSeparatorIndex != - 1 ) portSeparatorIndex + 1 else origin.length
147+ }
148+
149+ for (index in hostStartIndex until origin.length) {
150+ when (origin[index]) {
151+ ' :' -> return index + 1
152+ ' /' -> return origin.length
153+ ' ?' -> return - 1
154+ }
155+ }
156+ return origin.length
157+ }
158+
137159internal fun isValidOrigin (origin : String ): Boolean {
138160 if (origin.isEmpty()) return false
139161 if (origin == " null" ) return true
@@ -148,17 +170,11 @@ internal fun isValidOrigin(origin: String): Boolean {
148170
149171 if (! protoValid) return false
150172
151- var portIndex = origin.length
152- for (index in protoDelimiter + 3 until origin.length) {
153- val ch = origin[index]
154- if (ch == ' :' || ch == ' /' ) {
155- portIndex = index + 1
156- break
157- }
158- if (ch == ' ?' ) return false
159- }
173+ val hostStartIndex = protoDelimiter + 3
174+ val portDigitStartIndex = findPortDigitStartIndex(origin, hostStartIndex)
175+ if (portDigitStartIndex == - 1 ) return false
160176
161- for (index in portIndex until origin.length) {
177+ for (index in portDigitStartIndex until origin.length) {
162178 val isTrailingSlash = index == origin.length - 1 && origin[index] == ' /'
163179 if (! origin[index].isDigit() && ! isTrailingSlash) return false
164180 }
@@ -175,8 +191,13 @@ internal fun normalizeOrigin(origin: String): String {
175191 } else {
176192 builder.append(origin)
177193 }
178- if (! builder.toString().substringAfterLast(" :" , " " ).matches(NUMBER_REGEX )) {
179- val port = when (builder.toString().substringBefore(' :' )) {
194+ val originWithoutTrailingSlash = builder.toString()
195+ val hostStartIndex = originWithoutTrailingSlash.indexOf(" ://" ) + 3
196+ val portDigitStartIndex = findPortDigitStartIndex(originWithoutTrailingSlash, hostStartIndex)
197+ val hasExplicitPort = portDigitStartIndex in originWithoutTrailingSlash.indices &&
198+ originWithoutTrailingSlash.substring(portDigitStartIndex).matches(NUMBER_REGEX )
199+ if (! hasExplicitPort) {
200+ val port = when (originWithoutTrailingSlash.substringBefore(' :' )) {
180201 " http" -> " 80"
181202 " https" -> " 443"
182203 else -> null
0 commit comments