0

更新:方法返回类型 ANY 而不是类型 Future[string]。要求返回 String 类型。

我正在使用 play.ws 库 2.6 发出 http 请求。这以前是通过 curl 请求完成的,但这仅使用基本身份验证。

下面是我的代码,我试图从这个函数返回一个 json 字符串,以便在另一种方法中反序列化。

import java.io.{File, InputStream}
import java.nio.file.Paths
import javax.inject._

import org.apache.commons.io.FileUtils

import play.api._
import play.api.http.HttpEntity
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current

import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

import sys.process._

@Singleton
class BuildService @Inject() (
ws: WSClient,
ec: ExecutionContext,
config: Configuration) {

    def bbApiRequest(requestUrl: String, timeout: FiniteDuration): 
        Future[String] = {
        val request = ws
            .url(requestUrl)
            .withAuth(
                "user", 
                "pw1234",
                WSAuthScheme.BASIC)
            .get()
        Await.result(request, timeout)
        val returner = request.map(_.json)
    } // <-- line 72 in below error points here.
} 

运行时会产生错误:

[error] C:\my_path\app\services\BuildService.scala:72: type mismatch;
[error]  found   : Unit
[error]  required: scala.concurrent.Future[String]
[error]         }
[error]         ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[info] Compiling 1 Scala source to C:\my_path\restapi\target\scala-
       2.12\classes...
[error] C:\my_path\restapi\app\services\BuildService.scala:72: type 
        mismatch;
[error]  found   : Unit
[error]  required: scala.concurrent.Future[String]
[error]         }
[error]         ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

我正在努力达到理想状态:

  • 一个字符串返回(案例类和json方法解包一个字符串)
  • 同步请求(如果异步我需要等待完成以进行应用程序)
  • 安全(允许使用令牌进行验证)

感谢任何帮助!

4

2 回答 2

1

这是我使用的功能:

// first work with Futures the Play Controller will support that!
def bbApiRequest(requestUrl: String): Future[String] = {

  // call the webservice with basic authentication
  wsClient.url(requestUrl)
    .withAuth("tester", "pwd123", WSAuthScheme.BASIC)
    .get()
    .map(checkStatus) // function that evaluates the HTTP Status
    .map(_.json) // get the json
    .map(Json.prettyPrint) // get it as string

}

我会直接创建一个case class喜欢: .map(jsValue => handleJson(jsValue.validate[YourModel])) // or create a model of it (instead)而不是.map(Json.prettyPrint)

编辑

这里有一个例子checkStatus

  protected def checkStatus(resp: WSResponse): WSResponse = {
    resp.status match {
      case Status.OK => resp
      case Status.NOT_FOUND => throw WebNotFoundException()
      case Status.FORBIDDEN | Status.UNAUTHORIZED => throw WebAccessForbiddenException()
      case Status.NOT_ACCEPTABLE => throw WebNotAcceptableException()
      case _ => throw WebBadStatusException(resp.status + " - " + resp.statusText.toString)
    }
  }

异常是我自己创建的。

于 2018-05-15T12:10:21.970 回答
0

授权也可以输入到函数中或从方法内的环境变量中检索(更容易管理)。

只需在 Await 调用上使用 .body 即可,它将输出转换为通用类型字符串。

package utils

import javax.inject._

import play.api._
import play.api.http.HttpEntity
import play.api.libs.ws._
import play.api.mvc._
import play.api.Play.current

import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

import sys.process._

@Singleton
class HTTPRequest @Inject() (
ws: WSClient,
ec: ExecutionContext,
config: Configuration) {

    def bbApiRequest(requestUrl: String, timeout: FiniteDuration) = {
        val request = ws
            .url(requestUrl)
            .withAuth(
                "user", 
                "PW123", 
                WSAuthScheme.BASIC)
            .get()
        Await.result(request, timeout).body
    }
}
于 2018-05-15T15:38:23.083 回答