diff --git a/url-dsl/src/main/scala/urldsl/language/QueryParameters.scala b/url-dsl/src/main/scala/urldsl/language/QueryParameters.scala index 659745b..387b6d1 100644 --- a/url-dsl/src/main/scala/urldsl/language/QueryParameters.scala +++ b/url-dsl/src/main/scala/urldsl/language/QueryParameters.scala @@ -169,15 +169,28 @@ object QueryParameters { final def simpleQueryParam[Q, A]( paramName: String, matching: Param => Either[A, Q], - creating: Q => Param + creating: Q => Param, + onParameterNotFound: Map[String, Param] => Either[A, ParamMatchOutput[Q]] )(implicit paramMatchingError: ParamMatchingError[A]): QueryParameters[Q, A] = factory[Q, A]( (params: Map[String, Param]) => params .get(paramName) .map(matching) .map(_.map(ParamMatchOutput(_, params - paramName))) // consumes that param - .getOrElse(Left(paramMatchingError.missingParameterError(paramName))), + .getOrElse(onParameterNotFound(params)), creating.andThen(paramName -> _).andThen(Map(_)) +) + + final def simpleQueryParam[Q, A]( + paramName: String, + matching: Param => Either[A, Q], + creating: Q => Param + )(implicit paramMatchingError: ParamMatchingError[A]): QueryParameters[Q, A] = + simpleQueryParam( + paramName, + matching, + creating, + onParameterNotFound = _ => Left(paramMatchingError.missingParameterError(paramName)) ) final def param[Q, A]( @@ -206,11 +219,11 @@ object QueryParameters { simpleQueryParam[List[Q], A]( paramName, (_: Param) match { - case Param(Nil) => Right(List[Q]()) + case Param(Nil) => Right(Nil) case Param(head :: tail) => tail .map(fromString.apply) - .foldLeft(fromString(head).map(List(_))) { (acc, next) => + .foldLeft(fromString(head).map(_ :: Nil)) { (acc, next) => for { firstResults <- acc nextResult <- next @@ -218,7 +231,9 @@ object QueryParameters { } .map(_.reverse) }, - q => Param(q.map(printer.apply)) + q => Param(q.map(printer.apply)), + // If `paramName` is not present in the parameters we should return an empty list. + onParameterNotFound = params => Right(ParamMatchOutput(Nil, params)) ) final lazy val dummyErrorImpl = QueryParametersImpl[DummyError] diff --git a/url-dsl/src/test/scala/urldsl/examples/QueryParamsExamples.scala b/url-dsl/src/test/scala/urldsl/examples/QueryParamsExamples.scala index 9c12dd4..0497803 100644 --- a/url-dsl/src/test/scala/urldsl/examples/QueryParamsExamples.scala +++ b/url-dsl/src/test/scala/urldsl/examples/QueryParamsExamples.scala @@ -41,6 +41,8 @@ final class QueryParamsExamples extends AnyFlatSpec with Matchers { */ listParam[Int]("other").matchRawUrl(sampleUrl).map(_.sorted) should be(Right(List(2, 3))) + listParam[String]("non-existent").matchRawUrl("http://foo.com/") should be(Right(Nil)) + /** You can compose several [[urldsl.language.QueryParameters]] with the `&` operator. */ (param[String]("bar") & param[String]("babar")).matchRawUrl(sampleUrl) should be( Right(("stuff", "other stuff")) @@ -137,6 +139,8 @@ final class QueryParamsExamples extends AnyFlatSpec with Matchers { """p1=hey&p2=one&p2=two""" ) + listParam[String]("p1").createPart(Nil) should be("") + /** Flatenning of tuple param */ (param[String]("p1") & param[(Int, Int)]("p2") & listParam[String]("p3")).createPart(("hey", 11, 22, List("one", "two"))) should be( """p1=hey&p2=11-22&p3=one&p3=two"""