Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.

Commit f762bee

Browse files
authored
[PIO-31] Move from spray to akka-http (#474)
1 parent c7d75f3 commit f762bee

File tree

27 files changed

+1001
-1202
lines changed

27 files changed

+1001
-1202
lines changed

LICENSE.txt

+2-3
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,6 @@ Binary distribution bundles
409409
com.sun.jersey # jersey-server # 1.9 (https://github.com/jersey/jersey-1.x)
410410
javax.xml.bind # jaxb-api # 2.2.2
411411
com.sun.xml.bind # jaxb-impl # 2.2.3-1
412-
org.jvnet.mimepull # mimepull # 1.9.5 (https://github.com/kohsuke/mimepull)
413412

414413
which are available under the CDDL v1.1 license (https://glassfish.java.net/public/CDDL+GPL_1_1.html)
415414

@@ -1708,9 +1707,8 @@ Binary distribution bundles
17081707
org.scala-lang # scala-reflect # 2.11.12 (http://scala-lang.org/)
17091708
org.scala-lang # scalap # 2.11.12 (http://scala-lang.org/)
17101709
org.scala-lang.modules # scala-java8-compat_2.11 # 0.7.0 (http://scala-lang.org/)
1711-
org.scala-lang.modules # scala-parser-combinators_2.11 # 1.0.4 (http://scala-lang.org/)
17121710
org.scala-lang.modules # scala-parser-combinators_2.11 # 1.0.6 (http://scala-lang.org/)
1713-
org.scala-lang.modules # scala-xml_2.11 # 1.0.3 (http://scala-lang.org/)
1711+
org.scala-lang.modules # scala-parser-combinators_2.11 # 1.1.0 (http://scala-lang.org/)
17141712
org.scala-lang.modules # scala-xml_2.11 # 1.0.5 (http://scala-lang.org/)
17151713
org.scala-lang.modules # scala-xml_2.11 # 1.0.6 (http://scala-lang.org/)
17161714

@@ -1782,3 +1780,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17821780
The following libraries are from the public domain.
17831781

17841782
org.tukaani # xz # 1.0 (http://tukaani.org/xz/java.html)
1783+
org.reactivestreams # reactive-streams # 1.0.2 (http://www.reactive-streams.org/)

common/build.sbt

+6-4
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ import PIOBuild._
2020
name := "apache-predictionio-common"
2121

2222
libraryDependencies ++= Seq(
23-
"io.spray" %% "spray-can" % "1.3.3",
24-
"io.spray" %% "spray-routing" % "1.3.3",
25-
"com.typesafe.akka" %% "akka-actor" % akkaVersion.value,
26-
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion.value)
23+
"com.typesafe.akka" %% "akka-actor" % akkaVersion.value,
24+
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion.value,
25+
"com.typesafe.akka" %% "akka-http" % "10.1.5",
26+
"org.json4s" %% "json4s-native" % json4sVersion.value,
27+
"com.typesafe.akka" %% "akka-stream" % "2.5.12"
28+
)
2729

2830
pomExtra := childrenPomExtra.value

common/src/main/resources/application.conf

-7
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,3 @@ akka {
33
loggers = ["akka.event.slf4j.Slf4jLogger"]
44
loglevel = "INFO"
55
}
6-
7-
spray.can {
8-
server {
9-
verbose-error-messages = "on"
10-
request-timeout = 35s
11-
}
12-
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.predictionio.akkahttpjson4s
19+
20+
// Referenced from https://github.com/hseeberger/akka-http-json
21+
// because of the difference of supported json4s version.
22+
import java.lang.reflect.InvocationTargetException
23+
24+
import akka.http.scaladsl.marshalling.{ Marshaller, ToEntityMarshaller }
25+
import akka.http.scaladsl.model.ContentTypeRange
26+
import akka.http.scaladsl.model.MediaType
27+
import akka.http.scaladsl.model.MediaTypes.`application/json`
28+
import akka.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller }
29+
import akka.util.ByteString
30+
import org.json4s.{ Formats, MappingException, Serialization }
31+
import scala.collection.immutable.Seq
32+
33+
/**
34+
* Automatic to and from JSON marshalling/unmarshalling using an in-scope *Json4s* protocol.
35+
*
36+
* Pretty printing is enabled if an implicit [[Json4sSupport.ShouldWritePretty.True]] is in scope.
37+
*/
38+
object Json4sSupport extends Json4sSupport {
39+
40+
sealed abstract class ShouldWritePretty
41+
42+
final object ShouldWritePretty {
43+
final object True extends ShouldWritePretty
44+
final object False extends ShouldWritePretty
45+
}
46+
}
47+
48+
/**
49+
* Automatic to and from JSON marshalling/unmarshalling using an in-scope *Json4s* protocol.
50+
*
51+
* Pretty printing is enabled if an implicit [[Json4sSupport.ShouldWritePretty.True]] is in scope.
52+
*/
53+
trait Json4sSupport {
54+
import Json4sSupport._
55+
56+
def unmarshallerContentTypes: Seq[ContentTypeRange] =
57+
mediaTypes.map(ContentTypeRange.apply)
58+
59+
def mediaTypes: Seq[MediaType.WithFixedCharset] =
60+
List(`application/json`)
61+
62+
private val jsonStringUnmarshaller =
63+
Unmarshaller.byteStringUnmarshaller
64+
.forContentTypes(unmarshallerContentTypes: _*)
65+
.mapWithCharset {
66+
case (ByteString.empty, _) => throw Unmarshaller.NoContentException
67+
case (data, charset) => data.decodeString(charset.nioCharset.name)
68+
}
69+
70+
private val jsonStringMarshaller =
71+
Marshaller.oneOf(mediaTypes: _*)(Marshaller.stringMarshaller)
72+
73+
/**
74+
* HTTP entity => `A`
75+
*
76+
* @tparam A type to decode
77+
* @return unmarshaller for `A`
78+
*/
79+
implicit def unmarshaller[A: Manifest](implicit serialization: Serialization,
80+
formats: Formats): FromEntityUnmarshaller[A] =
81+
jsonStringUnmarshaller
82+
.map(s => serialization.read(s))
83+
.recover { _ => _ =>
84+
{ case MappingException(_, ite: InvocationTargetException) => throw ite.getCause }
85+
}
86+
87+
/**
88+
* `A` => HTTP entity
89+
*
90+
* @tparam A type to encode, must be upper bounded by `AnyRef`
91+
* @return marshaller for any `A` value
92+
*/
93+
implicit def marshaller[A <: AnyRef](implicit serialization: Serialization,
94+
formats: Formats,
95+
shouldWritePretty: ShouldWritePretty =
96+
ShouldWritePretty.False): ToEntityMarshaller[A] =
97+
shouldWritePretty match {
98+
case ShouldWritePretty.False =>
99+
jsonStringMarshaller.compose(serialization.write[A])
100+
case ShouldWritePretty.True =>
101+
jsonStringMarshaller.compose(serialization.writePretty[A])
102+
}
103+
}

common/src/main/scala/org/apache/predictionio/authentication/KeyAuthentication.scala

+7-9
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,10 @@ package org.apache.predictionio.authentication
2323
* It is highly recommended to implement a stonger authentication mechanism
2424
*/
2525

26+
import akka.http.scaladsl.model.HttpRequest
27+
import akka.http.scaladsl.model.headers.HttpChallenge
28+
import akka.http.scaladsl.server.{AuthenticationFailedRejection, Rejection, RequestContext}
2629
import com.typesafe.config.ConfigFactory
27-
import spray.http.HttpRequest
28-
import spray.routing.authentication._
29-
import spray.routing.{AuthenticationFailedRejection, RequestContext}
30-
3130
import scala.concurrent.ExecutionContext.Implicits.global
3231
import scala.concurrent.Future
3332

@@ -42,19 +41,18 @@ trait KeyAuthentication {
4241
val param = "accessKey"
4342
}
4443

45-
def withAccessKeyFromFile: RequestContext => Future[Authentication[HttpRequest]] = {
44+
def withAccessKeyFromFile: RequestContext => Future[Either[Rejection, HttpRequest]] = {
4645
ctx: RequestContext =>
47-
val accessKeyParamOpt = ctx.request.uri.query.get(ServerKey.param)
46+
val accessKeyParamOpt = ctx.request.uri.query().get(ServerKey.param)
4847
Future {
49-
5048
val passedKey = accessKeyParamOpt.getOrElse {
5149
Left(AuthenticationFailedRejection(
52-
AuthenticationFailedRejection.CredentialsRejected, Nil))
50+
AuthenticationFailedRejection.CredentialsRejected, HttpChallenge("", None)))
5351
}
5452

5553
if (!ServerKey.authEnforced || passedKey.equals(ServerKey.get)) Right(ctx.request)
5654
else Left(AuthenticationFailedRejection(
57-
AuthenticationFailedRejection.CredentialsRejected, Nil))
55+
AuthenticationFailedRejection.CredentialsRejected, HttpChallenge("", None)))
5856

5957
}
6058
}

common/src/main/scala/org/apache/predictionio/configuration/SSLConfiguration.scala

+2-20
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,13 @@
1515
* limitations under the License.
1616
*/
1717

18-
1918
package org.apache.predictionio.configuration
2019

21-
/**
22-
* Created by ykhodorkovsky on 2/26/16.
23-
*/
24-
2520
import java.io.FileInputStream
2621
import java.security.KeyStore
27-
import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory}
2822

2923
import com.typesafe.config.ConfigFactory
30-
import spray.io.ServerSSLEngineProvider
24+
import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory}
3125

3226
trait SSLConfiguration {
3327

@@ -39,7 +33,6 @@ trait SSLConfiguration {
3933
private val keyAlias = serverConfig.getString("org.apache.predictionio.server.ssl-key-alias")
4034

4135
private val keyStore = {
42-
4336
// Loading keystore from specified file
4437
val clientStore = KeyStore.getInstance("JKS")
4538
val inputStream = new FileInputStream(
@@ -50,7 +43,7 @@ trait SSLConfiguration {
5043
}
5144

5245
// Creating SSL context
53-
implicit def sslContext: SSLContext = {
46+
def sslContext: SSLContext = {
5447
val context = SSLContext.getInstance("TLS")
5548
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
5649
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
@@ -60,15 +53,4 @@ trait SSLConfiguration {
6053
context
6154
}
6255

63-
// provide implicit SSLEngine with some protocols
64-
implicit def sslEngineProvider: ServerSSLEngineProvider = {
65-
ServerSSLEngineProvider { engine =>
66-
engine.setEnabledCipherSuites(Array(
67-
"TLS_RSA_WITH_AES_256_CBC_SHA",
68-
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
69-
"TLS_RSA_WITH_AES_128_CBC_SHA"))
70-
engine.setEnabledProtocols(Array("TLSv1", "TLSv1.2", "TLSv1.1"))
71-
engine
72-
}
73-
}
7456
}

0 commit comments

Comments
 (0)