我在Spray.io中定义了以下路由.真正奇怪的是,每当我打电话时,/user/8dsdf974jj它实际上都会运行以下三条路线.幽默地,我注意到了,因为我同时收到了20封发送给我的验证电子邮件.
pathPrefix("user") {
pathPrefix(PathElement) { id =>
path("") {
get { // code here }
} ~
path("verify" / "request") {
get { // code here }
} ~
path("verify" / "confirm") {
get { // code here }
}
}
}
Run Code Online (Sandbox Code Playgroud)
有人能解释为什么路径不会终止路由树吗?谢谢您的帮助.
我正在尝试使用spala 2.11喷涂运行一个简单的"hello world"服务器:
import spray.routing.SimpleRoutingApp
import akka.actor.ActorSystem
object SprayTest extends App with SimpleRoutingApp {
implicit val system = ActorSystem("my-system")
startServer(interface = "localhost", port = 8080) {
path("hello") {
get {
complete {
<h1>Say hello to spray</h1>
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我收到以下编译错误:
Multiple markers at this line
- not found: value port
- bad symbolic reference to spray.can encountered in class file 'SimpleRoutingApp.class'. Cannot
access term can in package spray. The current classpath may be missing a definition for spray.can, …Run Code Online (Sandbox Code Playgroud) 喷雾很难!! 我现在知道我对HTTP协议的了解还不够,API设计也不容易.但是,我仍然非常想要我的练习应用程序.我正在为POST/PUT/DELETE方法编写此身份验证.看来至少有两种方法可以做到这一点:BasicAuth或编写自定义指令.
我找到了这篇文章:
BasicAuth:https://github.com/jacobus/s4/blob/master/src/main/scala/s4/rest/S4Service.scala
我正在尝试,因为它看起来很简单.
编译和运行阶段很好,服务器运行.但是,当我尝试发送PUT请求来测试实现时(使用Python的Httpie :) http PUT 127.0.0.1:8080/sec-company/casper username=username token=123,反馈是:HTTP/1.1 404 Not Found
这是我的路线:
pathPrefix("sec-company") {
path("casper") {
//first examine username and token
authenticate(BasicAuth(CustomUserPassAuthenticator, "company-security")) {userProfile =>
post { ctx =>
entity(as[Company.Company]) { company =>
complete {
company
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的实现UserPassAuthenticator:
object CustomUserPassAuthenticator extends UserPassAuthenticator[UserProfile] {
def apply(userPass: Option[UserPass]) = Promise.successful(
userPass match {
case Some(UserPass(user, token)) => getUserProfile(user, token)
case _ => None
} …Run Code Online (Sandbox Code Playgroud) 我想将带有Option[DateTime]参数的case类转换为可由API提供的spray-json对象.使用spray-json我有一个自定义的JsonFormat
object JsonImplicits extends DefaultJsonProtocol {
implicit object PostJsonFormat extends RootJsonFormat[Post] {
def write(p: Post) = JsObject(
"title" -> JsString(p.title),
"content" -> JsString(p.content),
"author" -> JsString(p.author),
"creationDate" -> JsString(p.creationDate.getOrElse(DateTime.now))
)
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到:
overloaded method value apply with alternatives:
(value: String)spray.json.JsString <and>
(value: Symbol)spray.json.JsString
cannot be applied to (com.github.nscala_time.time.Imports.DateTime)
"creationDate" -> JsString(p.creationDate.getOrElse(DateTime.now))
Run Code Online (Sandbox Code Playgroud)
当我尝试编译它时,无论我尝试什么,我似乎无法将DateTime对象转换为字符串.例如,当我试着打电话时,toString我得到了
ambiguous reference to overloaded definition,
both method toString in class AbstractDateTime of type (x$1: String, x$2: java.util.Locale)String
and method toString in class AbstractDateTime …Run Code Online (Sandbox Code Playgroud) 我正在努力学习斯卡拉期货.正如标题所示,在我看来,Await.result最终必须在程序中的某个时刻调用,以便将未来的值提取到Scala字段中.到目前为止,这是我的代码.我在这里查询一个任意的uri并将它映射到一个case类,Address假设这个Addresscase类有一个字段,final_balance.
case class Address(final_balance:Double)
def getAddress(bitcoinAddress: String)(format: DataFormat): Future[Address] = {
val uri: String = "http://example.com"
val response: Future[HttpResponse] = (IO(Http) ? HttpRequest(GET, Uri(uri))).mapTo[HttpResponse]
implicit val addressJsonFormat = AddressJsonProtocol.addressFormat
val address: Future[Address] = response.flatMap { x =>
x match {
case HttpResponse(_, entity, _, _) =>
Future(entity.asString.parseJson.convertTo[Address])
}
}
address
}
def getFinalBalance(address: String): Double = {
val futureAddress: Future[Address] = QueryAddress.getAddress(address)(Json)
val finalBalance:Future[Double] = for { a <- futureAddress } yield …Run Code Online (Sandbox Code Playgroud) 根据文档,Spray允许用户记录请求和响应.
但是,出于某些原因,我似乎无法使其发挥作用.
这就是我在"路由方面"所拥有的
def generateRoute = pathPrefix("session") {
logRequest("session reached") {
path("new") {
logRequest("session new reached") {
post { entity(as[Initiate]) { sessionInfo =>
logRequest("session new post reached") {
complete("pass\n")
}
}
/// the rest of the braces
Run Code Online (Sandbox Code Playgroud)
这是我配置中的内容:
akka {
loglevel = DEBUG
loggers = ["akka.event.slf4j.Slf4jLogger"]
}
Run Code Online (Sandbox Code Playgroud)
这是我在日志中看到的内容:
app 11/29 13:02:35 DEBUG[sys-tracker-akka.actor.default-dispatcher-4] a.i.TcpListener - New connection accepted
app 11/29 13:02:36 DEBUG[sys-tracker-akka.actor.default-dispatcher-4] s.c.s.HttpServerConnection - Dispatching POST request to http://localhost:8080/session/new to handler Actor[akka://sys-tracker/system/IO-TCP/selectors/$a/1#2086889080]
app 11/29 13:02:36 DEBUG[sys-tracker-akka.actor.default-dispatcher-6] s.c.s.HttpServerConnection - Connection …Run Code Online (Sandbox Code Playgroud) 我正在忙着将我们的Spring/Groovy应用程序之一迁移到Spray/Scala.我对Spray很新,所以如果这是一个初学者问题,请原谅我.
目标是模拟我们的日志记录拦截器,它记录每个请求/响应的各种数据.在这部分代码中有很多逻辑,所以它不是一个简单的日志行.此外,我想用这个逻辑包装所有请求.
现有的Groovy/Spring拦截器:
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler {
//do some logging logic
}
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//do some more logging logic
}
Run Code Online (Sandbox Code Playgroud)
我的Scala演员看起来像这样
class BootServiceActor extends Actor with ViewingController with LazyLogging with ViewingWire {
def actorRefFactory = context
implicit val ctx = context.dispatcher
def receive = runRoute(route)(exceptionHandler, RejectionHandler.Default, context,
RoutingSettings.default, LoggingContext.fromActorRefFactory)
}
Run Code Online (Sandbox Code Playgroud) 如果我们考虑生产级REST API,我们应该尽可能多地使用非阻塞,例如
def insertDbAsync(rows: RowList): Future[Unit] = ...
...
val route =
path("database" / "insertRowList") {
post {
entity(as[RowList]) { rows =>
log.info(s"${rows.length} rows received")
val async = insertDbAsync(rows)
onComplete(async) {
case Success(response) =>
complete("success")
case Failure(t) =>
complete("error")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为答案很可能是'是',但在决定什么应该和不应该是阻止代码时有哪些指导原则,以及为什么?
在检查喷雾api的吞吐量时.
场景:25个并发用户
Os:免费BSD
内存:2GB
无核心:2
在大约13个并发用户中,我收到以下错误.
[ERROR] [06/29/2015 05:01:56.407] [default-akka.actor.default-dispatcher-2] [ActorSystem(default)] Uncaught error from thread [default-akka.actor.default-dispatcher-2] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:714)
at scala.concurrent.forkjoin.ForkJoinPool.tryAddWorker(ForkJoinPool.java:1672)
at scala.concurrent.forkjoin.ForkJoinPool.deregisterWorker(ForkJoinPool.java:1795)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:117)
Run Code Online (Sandbox Code Playgroud)
Akka和Spray Conf从默认值更改:
akka{
tcp{
register-timeout = 20s
}
}
spray.can {
request-timeout = 30 s
bind-timeout = 30s
unbind-timeout = 5s
registration-timeout = 30s
}
http.spray.can {
server{
pipelining-limit = 50
}
}
Run Code Online (Sandbox Code Playgroud)
导致OutOfMemmoryError的原因.从路由器actor抛出异常
我创建了一个案例类来存储我的一些数据.案例类如下所示:
case class Job(id: Option[Int], title: String, description: Option[String],
start: Date, end: Option[Date], customerId: Int)
Run Code Online (Sandbox Code Playgroud)
我使用以下格式化程序来编写/读取我的JSON对象:
implicit val jobFormat = jsonFormat6(Job.apply)
Run Code Online (Sandbox Code Playgroud)
我在写/读时遇到了一些问题,因为我需要在JSON中添加一个字段(但不是在case类中),例如:"test":"test".我尝试使用以下代码编写自定义读/写:
implicit object jobFormat extends RootJsonFormat[Job] {
override def read(json: JsValue): JobRow = ???
override def write(job: Job): JsValue = ??
}
Run Code Online (Sandbox Code Playgroud)
我无法获得正常工作的代码,有人可以帮我解决这个问题吗?
提前致谢!