Почему клиент Akka Http создает исключение для любого другого из статуса успешного ответа? - PullRequest
0 голосов
/ 16 января 2020

Я использую Akka Http (v. 10.1.10) для создания клиента с прокси. Каждый раз, когда ответ отличается от успешного, вместо правильной сущности ответа я получаю ошибку:

akka.http.impl.engine.client.ProxyConnectionFailedException: The HTTP(S) proxy rejected to open a connection to hahahahahhahaahahhahaadsfsd.com:80 with status code: 503 Service Unavailable
    at akka.http.impl.engine.client.HttpsProxyGraphStage$$anon$1$$anon$4.onPush(HttpsProxyGraphStage.scala:143)
    at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:523)
    at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:409)
    at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:606)
    at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:485)
    at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:581)
    at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:749)
    at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:764)
    at akka.actor.Actor.aroundReceive(Actor.scala:539)
    at akka.actor.Actor.aroundReceive$(Actor.scala:537)
    at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:671)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:612)
    at akka.actor.ActorCell.invoke(ActorCell.scala:581)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:268)
    at akka.dispatch.Mailbox.run(Mailbox.scala:229)
    at akka.dispatch.Mailbox.exec(Mailbox.scala:241)
    at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

В основном коде Akka Http я обнаружил, что это реализация обработчика для прокси, которая намеренно вызывает ошибку, если ответ не является успешным:

          case Connecting =>
            val proxyResponse = grab(bytesIn)
            parser.parseBytes(proxyResponse) match {
              case NeedMoreData =>
                pull(bytesIn)
              case ResponseStart(_: StatusCodes.Success, _, _, _, _) =>
                var pushed = false
                val parseResult = parser.onPull()
                require(parseResult == ParserOutput.MessageEnd, s"parseResult should be MessageEnd but was $parseResult")
                parser.onPull() match {
                  // NeedMoreData is what we emit in overridden `parseMessage` in case input.size == offset
                  case NeedMoreData =>
                  case RemainingBytes(bytes) =>
                    push(sslOut, bytes) // parser already read more than expected, forward that data directly
                    pushed = true
                  case other =>
                    throw new IllegalStateException(s"unexpected element of type ${other.getClass}")
                }
                parser.onUpstreamFinish()

                log.debug(s"HTTP(S) proxy connection to {}:{} established. Now forwarding data.", targetHostName, targetPort)

                state = Connected
                if (isAvailable(bytesOut)) pull(sslIn)
                if (isAvailable(sslOut)) pull(bytesIn)
              case ResponseStart(statusCode, _, _, _, _) =>
                failStage(new ProxyConnectionFailedException(s"The HTTP(S) proxy rejected to open a connection to $targetHostName:$targetPort with status code: $statusCode"))
              case other =>
                throw new IllegalStateException(s"unexpected element of type $other")
            }

Мне интересно, в чем причина такой реализации, если кто-то знает? И как обойти это, чтобы получить объект ответа вместо ошибки, когда ответ от сервера не успешен?

1 Ответ

0 голосов
/ 16 января 2020

Попробуйте восстановить функцию для захвата и возврата нужного вам объекта ответа.


    Http().singleRequest(HttpRequest(
      uri = url
    )).map(response => {
      response
    }) recover {
      case e: Exception => {
        e.printStackTrace()
        // anything you want to return
        HttpResponse(StatusCodes.OK)
      }
    }

...