如何在 Scala 中使用 XML.load 处理 403?

发布于 2024-11-03 12:09:05 字数 503 浏览 1 评论 0原文

我正在编写一个 Scala 客户端来与 Amazon 的 RESTful 产品 API 交互。要返回给定请求的 XML,我正在使用:

XML.load(uri)

这工作正常,除了有时亚马逊不喜欢嵌入 uri 中的签名,因此它返回 403(以及有效的 XML 错误报告)。不幸的是,这个 403 在 XML.load 中抛出异常:

java.io.IOException: Server returned HTTP response code: 403 for URL: http://...

理想情况下,我想要一种标记异常但无论如何返回错误 XML 的方法。是否有一种简单的方法可以使用我缺少的 XML.load 来执行此操作,或者我需要将其分解为两阶段“获取然后加载”过程?

I'm writing a Scala client to interface with Amazon's RESTful Product API. To return the XML for a given request I'm using:

XML.load(uri)

This is working fine, except that sometimes when Amazon doesn't like e.g. the Signature embedded in uri and so it returns a 403 (along with a valid XML error report). Unfortunately this 403 throws an exception within XML.load:

java.io.IOException: Server returned HTTP response code: 403 for URL: http://...

Ideally I'd like a way of flagging up the exception but returning the error XML anyway. Is there a simple way of doing this with XML.load I'm missing, or will I need to break it down into a two-stage get-then-load process?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

那支青花 2024-11-10 12:09:05

XML.load(URL) 利用 Java 的 java.net.URL.openStream(),它以一种不让您访问“错误流”的方式抛出 IOException,

因此,您可以制作更长的一系列的调用来获取一个InputStream,然后你可以通过XML.load 这个结果InputStream。

使用 URL.openConnection() (而不是 URL.openStream),然后从 try 块中调用 HttpURLConnection.getInputStream()。
然后在 catch 块中调用 HttpURLConnection.getErrorStream()。

http://download.oracle .com/javase/6/docs/api/java/net/URL.html#openConnection%28%29

http://download.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#getErrorStream%28 %29

现在您可以对生成的 InputStream 调用 XML.load(InputStream)。

希望这足以让您上路。

XML.load(URL) makes use of Java's java.net.URL.openStream(), which is throwing the IOException in a way that doesn't give you any access to the "Error Stream"

So, you can make a more long-winded sequence of calls to get an InputStream, and then you can XML.load this resulting InputStream.

Use URL.openConnection() (instead of URL.openStream), and then call HttpURLConnection.getInputStream() from within a try block.
Then in your catch block, call HttpURLConnection.getErrorStream().

http://download.oracle.com/javase/6/docs/api/java/net/URL.html#openConnection%28%29

http://download.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html#getErrorStream%28%29

Now you can call XML.load(InputStream) on the resulting InputStream.

Hope that's enough to set you on your way.

情徒 2024-11-10 12:09:05

在 http 调度 (http://dispatch.databinder.net/About) 中,这是可行的,如下所示:

import dispatch.Http._
import dispatch.{StatusCode, Http}
import xml.XML

try {
  Http("http://localhost/notthere" <> println)
} catch {
  case StatusCode(404, data) =>
    println(XML.loadString(data))
}

In http dispatch (http://dispatch.databinder.net/About) this is doable like this:

import dispatch.Http._
import dispatch.{StatusCode, Http}
import xml.XML

try {
  Http("http://localhost/notthere" <> println)
} catch {
  case StatusCode(404, data) =>
    println(XML.loadString(data))
}
二货你真萌 2024-11-10 12:09:05

这是我最终编写的代码,非常感谢上面的所有指导。 (如果以下内容可以改进/变得更惯用,请告诉我):

val url = new URL("http://ecs.amazonaws...")

val connection = url.openConnection() match {
  case x: HttpURLConnection => x
  case _ => throw new ClassCastException
}

val responseCode = connection.getResponseCode();

val data = try {
  connection.getInputStream()
} catch {
  case e => connection.getErrorStream()
}

val xml = XML.load(data)
return (responseCode, xml)

This is the code I ended up writing, many thanks for all the guidance above. (If anything in the below could be improved/made more idiomatic, do please let me know):

val url = new URL("http://ecs.amazonaws...")

val connection = url.openConnection() match {
  case x: HttpURLConnection => x
  case _ => throw new ClassCastException
}

val responseCode = connection.getResponseCode();

val data = try {
  connection.getInputStream()
} catch {
  case e => connection.getErrorStream()
}

val xml = XML.load(data)
return (responseCode, xml)
ゃ懵逼小萝莉 2024-11-10 12:09:05

对于此级别的控制,您可以使用 ConstructingParser 。该链接中包含一个示例。您可以使用此技术通过两个不同的步骤获取原始Source 并从中构造XML。

For this level of control you may use ConstructingParser. An example is included in that link. You obtain the raw Source and construct XML from it in two distinct steps using this technique.

如果没有你 2024-11-10 12:09:05

这是我的解决方案,需要将 scalaj 添加到项目中。

步骤1:将scalaj添加到build.sbt(我的scala版本是2.11.7,但它仍然说我的scala版本是由libraray依赖项之一更新的。所以我添加ivyscala来强制更新)

libraryDependencies += "org.scalaj" %% "scalaj-http" % "1.1.4"

ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }

步骤2:导入库到代码

import scalaj.http.Http
import scala.xml.XML

步骤3:使用http身体摆脱403;当您收到 403 异常时,将这些代码添加到异常部分。

val response = Http(your_url)
val responseExecute = response.execute()
val responseBody = responseExecute.body.toString
val xml = XML.loadString(responseBody)

Here is my solution which needs to add scalaj to project.

Step1: add scalaj to build.sbt (my scala version is 2.11.7 , but it still said my scala version was updated by one of libraray dependcies. so i add ivyscala to force update)

libraryDependencies += "org.scalaj" %% "scalaj-http" % "1.1.4"

ivyScala := ivyScala.value map { _.copy(overrideScalaVersion = true) }

Step2: import library to code

import scalaj.http.Http
import scala.xml.XML

Step3: use http body to get rid of 403; add these codes to exception part when you get 403 exception.

val response = Http(your_url)
val responseExecute = response.execute()
val responseBody = responseExecute.body.toString
val xml = XML.loadString(responseBody)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文