我正在调用API,但大多数情况下我一直收到错误:" 自SSL连接已关闭后删除关闭 "和" 过早连接关闭(服务器似乎不支持请求流水线)". "就像90%的时间我得到了这个错误,这意味着:在非常罕见的情况下,查询会返回它应该的数据.
为了确保这不是API的服务器问题,我使用Node.js(Express和Request libs)复制相同的查询,并且它每次都有效.这让我几乎可以肯定是一个喷雾虫.
这是代码的示例:
case class MyClass(user: String, pass: String)
class MyActor extends Actor {
import spray.client.pipelining._
import spray.http.BasicHttpCredentials
import spray.http.{HttpRequest,HttpResponse}
import scala.concurrent.Future
import context.dispatcher
def receive = {
case myClass: MyClass => {
val credentials: BasicHttpCredentials = BasicHttpCredentials(myClass.user, myClass.pass)
val url: String = "https://myApi?params=values"
val request: HttpRequest = Get(url) ~> addCredentials(credentials)
val pipeline = sendReceive
val response: Future[HttpResponse] = pipeline(request)
val finalRes: Future[String] = response.map{ r =>
println(r)
r.entity.asString
}
finalRes pipeTo …
Run Code Online (Sandbox Code Playgroud) 我有一个简单的喷雾客户端:
val pipeline = sendReceive ~> unmarshal[GoogleApiResult[Elevation]]
val responseFuture = pipeline {Get("http://maps.googleapis.com/maps/api/elevation/jsonlocations=27.988056,86.925278&sensor=false") }
responseFuture onComplete {
case Success(GoogleApiResult(_, Elevation(_, elevation) :: _)) =>
log.info("The elevation of Mt. Everest is: {} m", elevation)
shutdown()
case Failure(error) =>
log.error(error, "Couldn't get elevation")
shutdown()
}
Run Code Online (Sandbox Code Playgroud)
完整代码可以在这里找到.
我想模拟服务器的响应来测试Success
和Failure
案例中的逻辑.我找到的唯一相关信息是在这里,但我无法使用蛋糕模式来模拟sendReceive方法.
任何建议或例子将不胜感激.
使用spray的流水线操作来发出这样的HTTP请求时:
val urlpipeline = sendReceive ~> unmarshal[String]
urlpipeline { Get(url) }
Run Code Online (Sandbox Code Playgroud)
有没有办法为请求指定超时以及它应该为该特定请求重试的次数?
我发现的所有文档只引用了一个配置(即便如此,我似乎无法让它工作).
谢谢
我在Scala中使用Akka actor从外部服务(HTTP get请求)下载资源.外部服务的响应是JSON,我必须使用分页(提供程序非常慢).我想在10个线程中同时下载所有分页结果.我使用这样的URL来下载块:http://service.com/itmes? limit = 50& offset = 1000
我创建了以下管道:
ScatterActor => RoundRobinPool[10](LoadChunkActor) => Aggreator
Run Code Online (Sandbox Code Playgroud)
ScatterActor获取要下载的项目的总数,并将其划分为块.我创建了10个LoadChunkActor来同时处理任务.
override def receive: Receive = {
case LoadMessage(limit) =>
val offsets: IndexedSeq[Int] = 0 until limit by chunkSize
offsets.foreach(offset => context.system.actorSelection(pipe) !
LoadMessage(chunkSize, offset))
}
Run Code Online (Sandbox Code Playgroud)
LoadChunkActor使用Spray发送请求.演员看起来像这样:
val pipeline = sendReceive ~> unmarshal[List[Items]]
override def receive: Receive = {
case LoadMessage(limit, offset) =>
val uri: String = s"http://service.com/items?limit=50&offset=$offset"
val responseFuture = pipeline {Get(uri)}
responseFuture onComplete {
case Success(items) => aggregator ! Loaded(items) …
Run Code Online (Sandbox Code Playgroud) 我有这两个错误:
Error:(39, 20) Cannot find an implicit ExecutionContext. You might pass
an (implicit ec: ExecutionContext) parameter to your method
or import scala.concurrent.ExecutionContext.Implicits.global.
val pipeline = sendReceive
^
Error:(39, 20) not enough arguments for method sendReceive: (implicit refFactory: akka.actor.ActorRefFactory, implicit executionContext: scala.concurrent.ExecutionContext, implicit futureTimeout: akka.util.Timeout)spray.client.pipelining.SendReceive.
Unspecified value parameter executionContext.
val pipeline = sendReceive
^
Run Code Online (Sandbox Code Playgroud)
我的代码是:
import scala.util.{Success, Failure}
import scala.concurrent.duration._
import akka.actor.ActorSystem
import akka.pattern.ask
import akka.event.Logging
import akka.io.IO
import spray.can.Http
import spray.client.pipelining._
import spray.util._
import argonaut._, Argonaut._
object test {
case …
Run Code Online (Sandbox Code Playgroud) 我想使用Spray将多部分表单发布到服务器.特别是我想张贴一张图片.
我遇到麻烦的是文件到多部分的编组.尽管在Spray中他们提到了默认的Marshaller,但我似乎无法将两者结合在一起.
我目前正在使用Spray 1.0-M7,因为我没有迁移到Scala 2.10,如果示例可以符合该分支,那将是非常好的.
我现在拥有的是:
val bis = new BufferedInputStream(new FileInputStream(file))
val bArray = Stream.continually(bis.read).takeWhile(-1 !=).map(_.toByte).toArray
Logger.error("About to post with spray")
pipeline(Post("/saveImageWithSpray", bArray))
Run Code Online (Sandbox Code Playgroud)
当然,我得到一个错误说:
For request 'POST /saveImageWithSpray' [Missing boundary header]
Run Code Online (Sandbox Code Playgroud)
我找到的大多数示例使用内容(作为[X])指令进行编组,但我没有使用Spray-routing,我只需要在另一个框架上构建的应用程序中使用spray-client执行post.
谢谢
编辑
我实际上设法像这样编组:
val pipeline = (
addHeader("Content-Type", "multipart/form-data")
~> sendReceive(conduit)
)
val bis = new BufferedInputStream(new FileInputStream(file, "UTF-8"))
val bArray = Stream.continually(bis.read).takeWhile(-1 !=).map(_.toByte).toArray
Logger.error("About to post with spray "+bArray.length.toString)
pipeline(Post("/saveImageWithSpray", MultipartFormData(Map(
"spray-file" -> BodyPart(
HttpEntity(Some(HttpBody(ContentType(MediaTypes.`image/gif`), bArray))),
HttpHeaders.`Content-Disposition`("form-data", Map("name" -> "spray-file","filename"->"Fuurin (Glass Wind Chime).gif"))::Nil
)
))))
Run Code Online (Sandbox Code Playgroud)
不幸的是,这仍然没有工作,数据正在转移,但服务器无法找到该文件. …
使用喷雾1.3.2和akka 2.3.6.(akka仅用于喷雾).
我需要读取大文件,并为每一行发出一个http请求.
我用迭代器逐行读取文件,并为每个项目发出请求.它成功地运行了一些线路,但在某些时候它开始失败:
akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://default/user/IO-HTTP#-35162984]] after [60000 ms]
.
我首先想到我重载了服务,所以我将"spray.can.host-connector.max-connections"设置为1.它运行得慢得多,但我得到了同样的错误.
这里的代码:
import spray.http.MediaTypes._
val EdnType = register(
MediaType.custom(
mainType = "application",
subType = "edn",
compressible = true,
binary = false,
fileExtensions = Seq("edn")))
val pipeline = (
addHeader("Accept", "application/json")
~> sendReceive
~> unmarshal[PipelineResponse])
def postData(data: String) = {
val request = Post(pipelineUrl).withEntity(HttpEntity.apply(EdnType, data))
val responseFuture: Future[PipelineResponse] = pipeline(request)
responseFuture
}
dataLines.map { d =>
val f = postData(d)
f.onFailure { case e => println("Error - …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Spray从我的Scala应用程序下载一个中等大小的文件,比如一个视频.
我需要的是下载文件,并且,对于我收到的每个chuck(可能是chuck维度是我将通过config设置的东西),跟踪整个过程的进度(也就像进度条一样).
另外,我想避免在保存之前将整个文件保存在内存中,而是在收到它时保存每个chuck(并记录它).
我查看了文档,有点在线.
但是,我似乎无法找到明确的方法.
我发现的唯一的事情是这个链接说当时喷雾客户端不支持这个用例,我应该直接使用喷雾罐......虽然没有例子,所以我仍然有点困惑.
任何人都可以建议一种方法吗?指出我正确的方向?你会如何下载30MB的文件?
谢谢
由于文档尚未准备好,我将在这里询问 akka 维护人员。
为什么 akka-httpUnmarshaler
返回Future[T]
而不是T
?这是我的目标。我想从 XML http 响应中解组类,类似于对 json 的处理方式。例如我想写
Unmarshal(HttpResponse.entity).to[Person]
Run Code Online (Sandbox Code Playgroud)
其中案例类及其解组器看起来像这样
case class Person(name: String, age: Int)
implicit val personUnmarshaller = Unmarshaller[NodeSeq, Person] { _ => xml =>
Future(Person((xml \\ "name").text, (xml \\ "age").text.toInt))
}
Run Code Online (Sandbox Code Playgroud)
它不会ScalaXmlSupport
使用 1.0-RC4 提供的版本进行编译,因为Unmarshaller[ResponseEntity,Person]
在范围内不可用。所以为了欺骗它我写了两个隐式转换
implicit def xmlUnmarshallerConverter[T](marsh: Unmarshaller[NodeSeq, T])(implicit mat: Materializer): FromEntityUnmarshaller[T] =
xmlUnmarshaller(marsh, mat)
implicit def xmlUnmarshaller[T](implicit marsh: Unmarshaller[NodeSeq, T], mat: Materializer): FromEntityUnmarshaller[T] =
defaultNodeSeqUnmarshaller.map(Unmarshal(_).to[T].value.get.get)
Run Code Online (Sandbox Code Playgroud)
它有效,但我不喜欢丑陋的.value.get.get
。有没有更优雅的方法来实现这个?
当我尝试获取像这样的亚马逊身份数据
val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
Run Code Online (Sandbox Code Playgroud)
使用适当的case类和formatter,我收到以下异常
UnsupportedContentType(预期'application/json')
因为亚马逊将其回复标记为文本/纯文本内容类型.他们也不关心Accept header param.是否有一种简单的方法可以告诉spray-json在解组时忽略它?
scala ×10
spray-client ×10
spray ×8
akka ×3
spray-json ×2
akka-http ×1
argonaut ×1
http ×1
pipeline ×1
scala-2.11 ×1
unit-testing ×1