Skip to content

Commit

Permalink
Merge branch 'master' into update/scala-library-2.13.5
Browse files Browse the repository at this point in the history
  • Loading branch information
theon authored Mar 8, 2021
2 parents c035120 + 9926399 commit a7a42f2
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ script: >
cd target &&
git clone https://github.com/lemonlabsuk/scala-uri-demo.git &&
cd scala-uri-demo &&
sbt -Dscala.ver=$TRAVIS_SCALA_VERSION -Dscala.uri.ver=3.0.0 test &&
sbt -Dscala.ver=$TRAVIS_SCALA_VERSION -Dscala.uri.ver=3.1.0 test &&
cd "$TRAVIS_BUILD_DIR"
jdk:
Expand Down
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
To include it in your SBT project from maven central:

```scala
"io.lemonlabs" %% "scala-uri" % "3.0.0"
"io.lemonlabs" %% "scala-uri" % "3.1.0"
```

## Migration Guides
Expand Down Expand Up @@ -190,6 +190,34 @@ val relativeUrl = Url.parse("/example?a=b")
relativeUrl.withScheme("http").withHost("www.example.com") // This is http://www.example.com/example?a=b
```

## Redacting URLs

It is possible to print out redacted URLs to logs with sensitive information either removed or replaced with a placeholder

Replacing with a placeholder:

```scala mdoc:reset
import io.lemonlabs.uri._
import io.lemonlabs.uri.redact._

val url = Url.parse("http://user:[email protected]?secret=123&last=yes")

// This returns http://xxx:[email protected]?secret=xxx&last=yes
url.toRedactedString(Redact.withPlaceholder("xxx").params("secret", "other").user().password())
```

Removing:

```scala mdoc:reset
import io.lemonlabs.uri._
import io.lemonlabs.uri.redact._

val url = Url.parse("http://user:[email protected]?secret=123&other=true")

// This returns http://example.com
url.toRedactedString(Redact.byRemoving.allParams().userInfo())
```

## Pattern Matching URIs

```scala mdoc:reset
Expand Down Expand Up @@ -816,13 +844,13 @@ The type class instances exist in the companion objects for these types.
* For `2.11.x` support use `scala-uri` `1.4.10` from branch [`1.4.x`](https://github.com/lemonlabsuk/scala-uri/tree/1.4.x)
* For `2.10.x` support use `scala-uri` `0.4.17` from branch [`0.4.x`](https://github.com/lemonlabsuk/scala-uri/tree/0.4.x)
* For `2.9.x` support use `scala-uri` `0.3.6` from branch [`0.3.x`](https://github.com/lemonlabsuk/scala-uri/tree/0.3.x)
* For Scala.js `1.x.x` support, use `scala-uri` `3.0.0`
* For Scala.js `1.x.x` support, use `scala-uri` `3.1.0`
* For Scala.js `0.6.x` support, use `scala-uri` `2.2.3`

Release builds are available in maven central. For SBT users just add the following dependency:

```scala
"io.lemonlabs" %% "scala-uri" % "3.0.0"
"io.lemonlabs" %% "scala-uri" % "3.1.0"
```

For maven users you should use (for 2.13.x):
Expand All @@ -831,7 +859,7 @@ For maven users you should use (for 2.13.x):
<dependency>
<groupId>io.lemonlabs</groupId>
<artifactId>scala-uri_2.13</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</dependency>
```

Expand Down
5 changes: 3 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ val sharedSettings = Seq(
organization := "io.lemonlabs",
libraryDependencies ++= Seq(
"org.typelevel" %%% "simulacrum-scalafix-annotations" % "0.5.4",
"org.scalatest" %%% "scalatest" % "3.2.5" % Test,
"org.scalatest" %%% "scalatest" % "3.2.6" % Test,
"org.scalatestplus" %%% "scalacheck-1-14" % "3.2.2.0" % Test,
"org.scalacheck" %%% "scalacheck" % "1.15.3" % Test,
"org.typelevel" %%% "cats-laws" % "2.4.2" % Test
Expand Down Expand Up @@ -116,7 +116,8 @@ val publishingSettings = Seq(
val previousVersions = (0 to 0).map(v => s"3.$v.0").toSet

val mimaExcludes = Seq(
ProblemFilters.exclude[ReversedMissingMethodProblem]("io.lemonlabs.uri.typesafe.QueryValueInstances1.*")
ProblemFilters.exclude[ReversedMissingMethodProblem]("io.lemonlabs.uri.typesafe.QueryValueInstances1.*"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("io.lemonlabs.uri.Url.*")
)

val mimaSettings = Seq(
Expand Down
2 changes: 1 addition & 1 deletion bumpversion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ git add shared/src/main/scala/io/lemonlabs/uri/inet/PublicSuffixes.scala
git commit -m"Update public suffixes"

echo "Running SBT to determine current version. Please wait..."
VER=$(sbt 'project scalaUriJVM' 'show version' | tail -n2 | head -n1 | cut -f2 -d' ')
VER=$(sbt 'project scalaUriJVM' 'show version' | tail -n1 | cut -f2 -d' ')

echo "Current version is $VER, what is the next version?"
read -r NEW_VER
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")

addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.18")

addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.25")
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.26")
71 changes: 70 additions & 1 deletion shared/src/main/scala/io/lemonlabs/uri/Uri.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java.util.Base64
import cats.{Eq, Order, Show}
import io.lemonlabs.uri.config.UriConfig
import io.lemonlabs.uri.parsing.{UriParser, UrlParser, UrnParser}
import io.lemonlabs.uri.redact.Redactor
import io.lemonlabs.uri.typesafe.{
Fragment,
PathPart,
Expand Down Expand Up @@ -175,7 +176,7 @@ sealed trait Url extends Uri {

/** Copies this Url but with the authority set as the given value.
*
* @param authority the authority host to set
* @param authority the authority to set
* @return a new Url with the specified authority
*/
def withAuthority(authority: Authority): SelfWithAuthority
Expand Down Expand Up @@ -333,6 +334,16 @@ sealed trait Url extends Uri {
def removeQueryString(): Self =
withQueryString(QueryString.empty)

/** Removes the user-info (both user and password) from this URL
* @return This URL without the user-info
*/
def removeUserInfo(): Self

/** Removes any password from this URL's user-info
* @return This URL without the password
*/
def removePassword(): Self

/** Transforms the Query String by applying the specified PartialFunction to each Query String Parameter
*
* Parameters not defined in the PartialFunction will be left as-is.
Expand Down Expand Up @@ -393,6 +404,16 @@ sealed trait Url extends Uri {
def filterQueryNames(f: String => Boolean): Self =
withQueryString(query.filterNames(f))

/** Transforms this URL by applying the specified Function to the user if it exists
* @return
*/
def mapUser(f: String => String): Self

/** Transforms this URL by applying the specified Function to the password if it exists
* @return
*/
def mapPassword(f: String => String): Self

/** Returns the apex domain for this URL.
*
* The apex domain is constructed from the public suffix for this URL's host prepended with the
Expand Down Expand Up @@ -452,6 +473,9 @@ sealed trait Url extends Uri {
case "" => ""
case s => "?" + s
}

def toRedactedString(redactor: Redactor)(implicit conf: UriConfig = UriConfig.default): String =
redactor.apply(this).toString(conf)
}

object Url {
Expand Down Expand Up @@ -553,6 +577,11 @@ final case class RelativeUrl(path: UrlPath, query: QueryString, fragment: Option

private[uri] def toString(c: UriConfig): String =
path.toString(c) + queryToString(c) + fragmentToString(c)

def removeUserInfo(): RelativeUrl = this
def removePassword(): RelativeUrl = this
def mapUser(f: String => String): RelativeUrl = this
def mapPassword(f: String => String): RelativeUrl = this
}

object RelativeUrl {
Expand Down Expand Up @@ -624,6 +653,41 @@ sealed trait UrlWithAuthority extends Url {
def withPort(port: Int): Self =
withAuthority(authority.copy(port = Some(port)))

def withUserInfo(ui: Option[UserInfo]): Self =
withAuthority(authority.copy(userInfo = ui))

/** Removes any user from this URL
*
* @return This URL without the user
*/
def removeUserInfo(): Self =
withAuthority(authority.copy(userInfo = None))

/** Removes any password from this URL
*
* @return This URL without the password
*/
def removePassword(): Self =
withUserInfo(userInfo.map(_.copy(password = None)))

/** Transforms this URL by applying the specified Function to the user if it exists
*
* @return
*/
override def mapUser(f: String => String): Self =
user.fold(self) { u =>
withUserInfo(userInfo.map(_.copy(user = f(u))))
}

/** Transforms this URL by applying the specified Function to the password if it exists
*
* @return
*/
override def mapPassword(f: String => String): Self =
password.fold(self) { p =>
withUserInfo(userInfo.map(_.copy(password = Some(f(p)))))
}

/** Returns the longest public suffix for the host in this URI. Examples include:
* `com` for `www.example.com`
* `co.uk` for `www.example.co.uk`
Expand Down Expand Up @@ -846,6 +910,11 @@ sealed trait UrlWithoutAuthority extends Url {
def subdomains: Vector[String] = Vector.empty
def shortestSubdomain: Option[String] = None
def longestSubdomain: Option[String] = None

def removeUserInfo(): Self = self
def removePassword(): Self = self
def mapUser(f: String => String): Self = self
def mapPassword(f: String => String): Self = self
}

object UrlWithoutAuthority {
Expand Down
Loading

0 comments on commit a7a42f2

Please sign in to comment.