http获取身体请求

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

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 

然后我得到了答复。

先感谢您

我使用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。

在为Celiometer API发送请求主体时,您使用HTTP PUT或POST请求。

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

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

您遇到的问题是,在您正在使用的URLConnection的实现中,您可以做什么和不能做什么的假设。 通常,您将使用HttpUrlConnection(当您转换为)时,它实际上将由您的jvm实现。 例如,这是一个特定于太阳的实现 。

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

如果你想要一个带主体的GET,你需要使用不同的连接方法,例如像apache-http-client这样的库。 你可以从看这个问题开始 。 开始时可能有更好的scala替代方案。

我在这里找到了一个简单的java解决方案,使用apache的httpclienthttpcorecommons-logging libs。

您需要创建一个类并扩展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; } } 

然后你就像这样使用它:

 HttpClient httpClient = HttpClientBuilder.create().build(); HttpGetWithEntity e = new HttpGetWithEntity(); e.setURI(new URI(yourURL)) e.setEntity(yourEntity); HttpResponse response = httpclient.execute(e); 

希望能帮助到你。

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

  1. 使用URL参数而不是JSON

根据文档,您可以使用URL参数或JSON。 您可以按照以下指定修改您的请求,以使用URL参数而不是JSON实现相同的操作。

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

    URL(“ 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%22值%22%3A%20%22gdfsf%22%7D%5D%7D “)

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

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

你也可以这样试试

@RequestMapping(value =“/ listcategories”,method = RequestMethod.GET)

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