从 scala-js 中的 url 中提取字段

Extracting fields from a url in scala-js

假设我有一个 url 像:

https://example.com/myproject/index-dev.html?_ijt=hsdlgh8h5g8hh489sajoej&a=102&b=a%20m&c=45&d=all&e=all

或者它可能是本地主机上的网页,例如:

localhost:63342/my project/index-dev.html?_ijt=hsdlgh8h5g8hh489sajoej&a=102&b=a%20m&c=45&d=all&e=all

我必须从二维数组中的这些 url 中提取查询字段(出现在“?”之后),如下所示:

_ijt    |    hsdlgh8h5g8hh489sajoej
a       |    102
b       |    a m
c       |    45
d       |    all
e       |    all

请注意,在 'b' 字段中,我已将“%20”替换为 space。这些字段(如 _ijt、a、b、c、d、e 等)的数量和名称可能会有所不同,例如 'a' 可以是 'city'。 到目前为止,我已经使用正则表达式提取出“?”之后的部分。然后使用 split("&") 方法将字符串拆分为多个字符串。 代码-

val url=localhost:63342/my project/index-dev.html?_ijt=hsdlgh8h5g8hh489sajoej&a=102&b=a%20m&c=45&d=all&e=all
val pattern="""(http|htpps)([A-Za-z0-9\:\/\%\-\.]*)\?""".r
val temp_url=pattern.replaceFirstIn(url,"")
val fields=temp_url.split("&")
println(fields.foreach(println))

输出为:

_ijt=hsdlgh8h5g8hh489sajoej
a=102
b=a%20m
c=45
d=all
e=all

但这似乎不是正确的做法。有帮助吗?

您需要对查询参数值调用 js.URIUtils.decodeURIComponent

val fields=temp_url.split("&").map(js.URIUtils.decodeURIComponent)

decodeURIComponentnative Javascript function, for which scala.js has a simple interface.

或者,您可以使用一些库来解析用 Scala 编写的 URL。解析 URL 通常存在安全隐患,而且很容易出错。库通常还支持满足相关标准/RFC 的任何输入。

使用 js.URIUtils.decodeURIComponent 准确解码 % 编码的字符。

令人惊讶的是,很难找到一个库来涵盖在 Scala.js 和 Scala(jvm) 中都能正常工作的全部内容。 java.net.URI 将为您提供查询字符串,而 java.net.URLDecoder.decode 将删除 URL 编码,但我还没有看到任何可以为您提供结构良好的查询片段的内容。这不是火箭科学,但它是如此常见,以至于您认为您不需要自己编写它。

Fastparse 将完成工作:

  val url = new java.net.URI("http://example.com/?a=1&b%20=b+is+2&c=#someAnchor?a=b")
  println(s"query string is: ${url.getQuery}")

  val individualElements =
    P(CharsWhile {
      case '&' | '=' | '#' => false
      case _ => true
    }.!.map(x => java.net.URLDecoder.decode(x, "UTF-8")))

  val keyValuePair: core.Parser[(String, Option[String]), Char, String] =
    individualElements ~ "=" ~ individualElements.?

  val pairs: core.Parser[Seq[(String, Option[String])], Char, String] =
    keyValuePair.rep(sep = "&")

  val parsed: Parsed[Seq[(String, Option[String])], Char, String] =
    pairs.parse(url.getQuery)

  parsed match {
    case Success(items, _) => println(s"items: ${items.toList}")
    // prints:
    // items: List((a,Some(1)), (b ,Some(b is 2)), (c,None))
  }

根据使用 "decodeURIComponent" 和 "java.net.URI" 的建议,我提出了这个快速而肮脏的解决方案,几乎肯定可以改进,但也许它有帮助:

def getUrlParameters(url: String): Map[String, Array[String]] = {
    java.net.URI.create(url).getQuery.split('&').map(js.URIUtils.decodeURIComponent).map { p =>
      val split = p.split('=')
      (split.head, split.tail.mkString("="))
    }.groupBy(_._1).map(m => m._1 -> m._2.map(_._2))
}

def getUrlParameter(url: String, parameter: String): Option[String] = {
    getUrlParameters(url).get(parameter).flatMap(_.headOption)
}

有点太晚了,但希望对来自 google 的任何人有所帮助;让:

def uriParameterExtractor(uri: String): Map[String, String] =
js.URIUtils.decodeURIComponent(uri).tail.split("&").toList.map(x => (x.split("=").head, x.split("=").tail.head)).toMap

然后使用 dom.window.location.search 参数调用此函数。您可以通过在此函数的结果上使用相应的键来查询任何感兴趣的参数值,即:

  • uriParameterExtractor(dom.window.location.search)("a") 将计算为 102

  • uriParameterExtractor(dom.window.location.search)("b") 将计算为 a m

  • 等等

使用这个 scala / scalajs 库: https://github.com/lemonlabsuk/scala-uri

import io.lemonlabs.uri.Url

val uri = Url.parse("http://example.com/path?a=b&a=c&d=e")
uri.query.paramMap // This is: Map("a" -> Vector("b", "c"), "d" -> Vector("e"))