http获取身体请求

时间:2014-11-28 00:36:06

标签: java scala http get

我知道你不应该发送带有正文的HTTP GET请求,但是ceilometer web api迫使我这样做。 我正在开发一个ceilometer scala客户端,所以我需要一个scala / java方法来获取一个正文的get请求。 到目前为止,我尝试使用beeClient(http://www.bigbeeconsultants.co.uk)和使用httpConnection的普通Java,但是我得到了404错误。 在卷曲中,我可以通过这种方式实现结果:

curl -X GET -H "X-Auth-Token: ..long long token here.." 
-H "Content-Type: application/json" 
-d '{"q": [{"field": "resource", "op": "eq", "value": "gdfsf"}]}'
http://137.204.57.150:8777/v2/meters/

这是我使用java HttpURLConnection的scala代码:

import java.io._
import java.net._
val token = "myToken"
val url = new URL("http://137.204.57.150:8777/v2/meters/")
val body = "{\"q\": [{\"field\": \"resource\", \"op\": \"eq\", \"value\": \"gdfsf\"}]}"
val bodyLenght = body.length.toString
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty("Content-Length", bodyLength)
connection.setRequestProperty("Accept", "*/*")
connection.setRequestProperty("X-Auth-Token", token)
connection.setDoInput(true)
connection.setDoOutput(true)
//SEND REQUEST
val wr = new DataOutputStream(connection.getOutputStream)
wr.write(body.getBytes)
wr.flush
wr.close
if (connection.getResponseCode == 200) 
    println("ok")
else
    println("error")

我的Java实现和curl命令之间有什么区别?我看不到任何东西,我试着检查curl的标题,用-v参数调用它,这就是我得到的:

* Hostname was NOT found in DNS cache
*   Trying 137.204.57.150...
* Connected to 137.204.57.150 (137.204.57.150) port 8777 (#0)
> GET /v2/meters/ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 137.204.57.150:8777
> Accept: */*
> X-Auth-Token: ...Token....
> Content-Type: application/json
> Content-Length: 60
> 
* upload completely sent off: 60 out of 60 bytes
* HTTP 1.0, assume close after body

然后我得到了答复。

提前谢谢

6 个答案:

答案 0 :(得分:3)

我使用jetty-client实现解决了这个问题,它允许以任何方式构建http请求。这是代码(它不是不可变的,但在scala中并没有那么糟糕):

val httpClient = new HttpClient()
httpClient.setConnectTimeout(connectTimeout)
httpClient.setFollowRedirects(false)
httpClient.setStopTimeout(readTimeout)
httpClient.start()
val resp = httpClient.newRequest(uri).
      method(HttpMethod.GET).
      header("X-Auth-Token",s).
      send()

看看我正在使用阻塞API,但是jetty也提供了Java NIO API。

答案 1 :(得分:1)

您在发送Celiometer API的请求正文时使用HTTP PUT或POST请求。

我检查了Ceilometer文档,发现所有请求主体的请求都使用HTTP PUT或POST方法。请求正文没有GET方法。 http://docs.openstack.org/developer/ceilometer/webapi/v2.html

答案 2 :(得分:1)

通常,规范不禁止任何类型的http请求(GET,DELETE等)上的正文,因此您可以根据需要执行此操作。但按照惯例,这是非典型的。

您遇到的问题是,您在执行您正在使用的URLConnection时可以做什么和不能做什么都有假设。通常,您将使用HttpUrlConnection(当您转换为)时,它实际上将由您的jvm实现。例如,这是sun specific implementation

如果你看一下这个实现,你会看到它假定你需要输出流的GET请求实际上是一个POST。

如果你想要一个带主体的GET,你需要使用不同的连接方法,例如像apache-http-client这样的库。你可以先看看this question。你可能会有更好的scala替代品。

答案 3 :(得分:1)

我使用apache的/* Copying data from array 'a' to array 'b */ for (i = 0; i < num; i++) { arr2[i] = arr1[i]; } httpclienthttpcore库找到了一个简单易用的java解决方案here

您需要创建一个类并扩展commons-logging,覆盖方法名称:

HttpEntityEnclosingRequestBase

然后你就这样使用它:

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;

public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
    public final static String METHOD_NAME = "GET";

    @Override
    public String getMethod() {
        return METHOD_NAME;
    }
}

希望它有所帮助。

答案 4 :(得分:0)

在检查了Ceilometer和cURL的文档后,我可以提出两点建议。

  1. 使用网址参数代替JSON
  2. 根据文档,您可以使用URL参数或JSON。您可以按照以下指定修改您的请求,以使用URL参数而不是JSON来实现相同的目标。

    URL("http://YOURHOST.COM:8777/v2/meters/?q.field=resource&q.op=eq&q.value=gdfsf")
    
    1. 如果您有特殊原因不对您的JSON方法使用网址参数,我猜编码是您的请求中缺少的内容。参数只需要在查询参数中发送,而不是在正文内容中发送。为此,我猜您需要根据您在问题中的请求尝试使用以下编码数据,如下所示。

      URL(&#34; http://YOURHOST.COM:8777/v2/meters/?q=%5B%7B%22field%22%3A%20%22resource%22%2C%20%22op%22%3A%20%22eq%22%2C%20%22value%22%3A%20%22gdfsf%22%7D%5D%7D&#34)

    2. 这里q是根查询参数名称,没有令牌我无法验证它。

      将YOURHOST.COM替换为您服务器的IP地址,因为即使将它们放入代码块后它也显示问题,请告诉我。

答案 5 :(得分:0)

你也可以尝试这样

@RequestMapping(value =&#34; / listcategories&#34;,method = RequestMethod.GET)

private ModelAndView getCategories() {
    ModelAndView modelAndView = new ModelAndView("list-of-categories");
    List<Category> categories = categoryService.getAllCategories();
    modelAndView.addObject("categories", categories);
    return modelAndView;
}