Android 上的 google-api-java-client JSON 解析器在 GAE 上生成空的 self.request.body

发布于 2024-10-14 18:46:33 字数 1102 浏览 5 评论 0原文

这与另一个有关网址缩短器的问题相关。 URL 缩短器的代码在独立 Java 和 Android 上都运行良好。但是,当重新使用此代码与自定义 Google App Engine 应用程序进行通信时,该代码在独立 Java 上运行得非常好,但在从 Android 使用时会生成空的 self.request.body。 为什么?

要重现此行为,请在 Android 上使用 Google 缩短网址运行以下代码: https://www.googleapis.com/urlshortener/v1/url,并使用指向网络服务器的自定义 URL。 独立 java 上的相同代码在两种情况下都会产生完全相同的请求(如预期的那样)。在Android上,在自定义URL的情况下,内容正文为空并且未设置内容长度。 我正在运行 google-api-java-client 1.2.2-alpha 和 jackson 1.7.1。

代码片段:

    HttpTransport transport = GoogleTransport.create();
    HttpRequest request = transport.buildPostRequest();

    // Change this URL below from Google Shortener URL, to a custom URL,
    // and the code on Android produces an empty body and Content-Length is not set
    request.setUrl("GoogleAppEngine url goes here");

    JsonCContent content = new JsonCContent();
    GenericData data = new GenericData();
    data.put("id", "whatever");
    content.data = data;
    request.content = content;
    HttpResponse response = request.execute();

This is related to another question about URL shortener. The code for URL shortener works fine, on both standalone Java and on Android. However, when re-using this code to communicate to a custom Google App Engine application, the code works perfectly fine on standalone Java, but produces an empty self.request.body when used from Android. Why?

To reproduce this behaviour, run the code below, on android, once with Google shortener URL:
https://www.googleapis.com/urlshortener/v1/url, and once with a custom URL to a web server.
The same code on standalone java produces exactly the same request (as expected) in both cases. On Android, in the case of custom URL, the content body is empty and content-length is not set.
I'm running google-api-java-client 1.2.2-alpha, with jackson 1.7.1.

The code snippet:

    HttpTransport transport = GoogleTransport.create();
    HttpRequest request = transport.buildPostRequest();

    // Change this URL below from Google Shortener URL, to a custom URL,
    // and the code on Android produces an empty body and Content-Length is not set
    request.setUrl("GoogleAppEngine url goes here");

    JsonCContent content = new JsonCContent();
    GenericData data = new GenericData();
    data.put("id", "whatever");
    content.data = data;
    request.content = content;
    HttpResponse response = request.execute();

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

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

发布评论

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

评论(1

烟若柳尘 2024-10-21 18:46:33

我已经做了一些调试,结果如下:

  • 默认情况下,Android 上的实现选择 Apache HTTP 客户端来执行低级传输。那里的代码是最低限度的,看起来好像没有正确设置请求的 Content-Type 和 Content-Length 。请求发出,但是,一些(最)挑剔的 Web 服务器会跳过正文。谷歌网络服务器似乎处理得很好。因此,它似乎适用于 Google 服务器,但不适用于其他 Web 服务器(这有点奇怪,但是,这超出了我的问题范围)。

  • 默认情况下,在 Java 上,java.net.HttpURLConnection 被选择用于低级 http 传输。这个实现更加详细,并且整齐地设置了所有必需的字段。 Content-Length 在那里,Content-Type 和所有其他字段也在那里。 JSON 内容被序列化,所有网络服务器都很高兴。包括我的自定义 GAE 应用程序。

因此,在 Android 上,以下解决方法可以解决该问题:

进行以下调用:

HttpTransport.setLowLevelHttpTransport(new com.google.api.client.javanet.NetHttpTransport());

在执行 request.execute() 之前

,在 Android 上,您将使用实际有效的传输(形成更整洁的请求)。

附注正如生活中经常发生的那样,我很懒,提出问题,希望有人能帮我解决。最终我自己进行了调试和解决,而且还必须编写所有这些内容。额外的工作——但我想,这对其他人都有好处。希望其他人会发现它有用。

PS.2。 google api java 客户端现在很棒;)感谢作者所做的出色工作。

I've done some debugging, and this is what turns out:

  • by default, implementation on Android picks Apache HTTP client to do the low level transport. The code there is bare minimum, and it looks as if it does not set properly the Content-Type and Content-Length of the request. The request goes out, but, some (most) picky web servers skip the body. Google web servers seem to be handling that ok. So, it seems to work fine for Google servers, but not for other web servers (this is a bit weird, but, this is beyond the point of my problem).

  • by default, on Java, java.net.HttpURLConnection is picked for low level http transport. This implementation is more verbose, and sets all the required fields neatly. Content-Length is there, so is the Content-Type and all the other fields. The JSON content gets serialised, and all the webservers are happy. Including my custom GAE app.

So, on Android, the following workaround solves the problem:

Put the following call:

HttpTransport.setLowLevelHttpTransport(new com.google.api.client.javanet.NetHttpTransport());

BEFORE you do the request.execute()

This way, on Android, you'll use the transport that actually works (more tidy request is formed).

ps. As it is often in life, I got lazy, asked the question, hoping for someone to solve it for me. Ended up debugging and solving it myself PLUS had to write all that. Extra work - but I guess, for everybody else benefits. Hope others will find it useful.

ps.2. google api java client rocks now ;) Thanks to the authors for putting up good work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文