aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradamw <adam@warski.org>2017-07-15 18:40:50 +0200
committeradamw <adam@warski.org>2017-07-15 18:40:50 +0200
commitb053c91551b924100fa8261e4f405bc40ce53147 (patch)
treefc79e2f9152fa0f9e4e1d4d50d4a00e69445fe3d
parenta3b03abe52b383488a3d8349d5b851d80050c4f2 (diff)
downloadsttp-b053c91551b924100fa8261e4f405bc40ce53147.tar.gz
sttp-b053c91551b924100fa8261e4f405bc40ce53147.tar.bz2
sttp-b053c91551b924100fa8261e4f405bc40ce53147.zip
Basic auth
-rw-r--r--build.sbt2
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/model/package.scala2
-rw-r--r--core/src/main/scala/com/softwaremill/sttp/package.scala19
-rw-r--r--tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala30
4 files changed, 51 insertions, 2 deletions
diff --git a/build.sbt b/build.sbt
index d96c7d8..f36138b 100644
--- a/build.sbt
+++ b/build.sbt
@@ -78,6 +78,6 @@ lazy val tests: Project = (project in file("tests"))
scalaTest,
"com.typesafe.scala-logging" %% "scala-logging" % "3.5.0",
"com.github.pathikrit" %% "better-files" % "3.0.0",
- "ch.qos.logback" % "logback-core" % "1.2.3"
+ "ch.qos.logback" % "logback-classic" % "1.2.3"
).map(_ % "test")
) dependsOn (core, akkaHttpHandler)
diff --git a/core/src/main/scala/com/softwaremill/sttp/model/package.scala b/core/src/main/scala/com/softwaremill/sttp/model/package.scala
index 982bc7c..3504866 100644
--- a/core/src/main/scala/com/softwaremill/sttp/model/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/model/package.scala
@@ -1,6 +1,6 @@
package com.softwaremill.sttp
-import java.io.{File, InputStream}
+import java.io.InputStream
import java.nio.ByteBuffer
import java.nio.file.Path
diff --git a/core/src/main/scala/com/softwaremill/sttp/package.scala b/core/src/main/scala/com/softwaremill/sttp/package.scala
index fdf537d..9061f5f 100644
--- a/core/src/main/scala/com/softwaremill/sttp/package.scala
+++ b/core/src/main/scala/com/softwaremill/sttp/package.scala
@@ -4,6 +4,7 @@ import java.io.{File, InputStream}
import java.net.URI
import java.nio.ByteBuffer
import java.nio.file.Path
+import java.util.Base64
import com.softwaremill.sttp.model._
@@ -145,6 +146,10 @@ package object sttp {
cookies(cs.map(c => (c.name, c.value)): _*)
def cookies(nvs: (String, String)*): RequestTemplate[U] =
header(CookieHeader, nvs.map(p => p._1 + "=" + p._2).mkString("; "))
+ def auth: SpecifyAuthScheme[U] =
+ new SpecifyAuthScheme[U](AuthorizationHeader, this)
+ def proxyAuth: SpecifyAuthScheme[U] =
+ new SpecifyAuthScheme[U](ProxyAuthorizationHeader, this)
/**
* If content type is not yet specified, will be set to `text/plain` with `utf-8` encoding.
@@ -224,6 +229,18 @@ package object sttp {
}
}
+ class SpecifyAuthScheme[U[_]](hn: String, rt: RequestTemplate[U]) {
+ def basic(user: String, password: String): RequestTemplate[U] = {
+ val c = new String(
+ Base64.getEncoder.encode(s"$user:$password".getBytes(Utf8)),
+ Utf8)
+ rt.header(hn, s"Basic $c")
+ }
+
+ def bearer(token: String): RequestTemplate[U] =
+ rt.header(hn, s"Bearer $token")
+ }
+
object RequestTemplate {
val empty: RequestTemplate[Empty] =
RequestTemplate[Empty](None, None, NoBody, Vector())
@@ -242,6 +259,8 @@ package object sttp {
private[sttp] val ContentLengthHeader = "Content-Length"
private[sttp] val SetCookieHeader = "Set-Cookie"
private[sttp] val CookieHeader = "Cookie"
+ private[sttp] val AuthorizationHeader = "Authorization"
+ private[sttp] val ProxyAuthorizationHeader = "Proxy-Authorization"
private val Utf8 = "utf-8"
private val ApplicationOctetStreamContentType = "application/octet-stream"
diff --git a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
index 28a5ac0..1ad5fc0 100644
--- a/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
+++ b/tests/src/test/scala/com/softwaremill/sttp/BasicTests.scala
@@ -10,6 +10,7 @@ import akka.http.scaladsl.model.DateTime
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.headers.CacheDirectives._
import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.server.directives.Credentials
import com.softwaremill.sttp.akkahttp.AkkaHttpSttpHandler
import com.typesafe.scalalogging.StrictLogging
import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
@@ -83,6 +84,15 @@ class BasicTests
}
}
}
+ } ~ path("secure_basic") {
+ authenticateBasic("test realm", {
+ case c @ Credentials.Provided(un)
+ if un == "adam" && c.verify("1234") =>
+ Some(un)
+ case _ => None
+ }) { userName =>
+ complete(s"Hello, $userName!")
+ }
}
private implicit val actorSystem: ActorSystem = ActorSystem("sttp-test")
@@ -130,6 +140,7 @@ class BasicTests
headerTests()
errorsTests()
cookiesTests()
+ authTests()
def parseResponseTests(): Unit = {
name should "parse response as string" in {
@@ -263,5 +274,24 @@ class BasicTests
))
}
}
+
+ def authTests(): Unit = {
+ val secureBasic = sttp.get(uri"$endpoint/secure_basic")
+
+ name should "return a 401 when authorization fails" in {
+ val req = secureBasic
+ val resp = forceResponse.force(req.send(responseAsString))
+ resp.code should be(401)
+ resp.header("WWW-Authenticate") should be(
+ Some("""Basic realm="test realm",charset=UTF-8"""))
+ }
+
+ name should "perform basic authorization" in {
+ val req = secureBasic.auth.basic("adam", "1234")
+ val resp = forceResponse.force(req.send(responseAsString))
+ resp.code should be(200)
+ resp.body should be("Hello, adam!")
+ }
+ }
}
}