我知道你不应该发送带有正文的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
然后我得到了答复。
提前谢谢
答案 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];
}
,httpclient
和httpcore
库找到了一个简单易用的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的文档后,我可以提出两点建议。
根据文档,您可以使用URL参数或JSON。您可以按照以下指定修改您的请求,以使用URL参数而不是JSON来实现相同的目标。
URL("http://YOURHOST.COM:8777/v2/meters/?q.field=resource&q.op=eq&q.value=gdfsf")
如果您有特殊原因不对您的JSON方法使用网址参数,我猜编码是您的请求中缺少的内容。参数只需要在查询参数中发送,而不是在正文内容中发送。为此,我猜您需要根据您在问题中的请求尝试使用以下编码数据,如下所示。
这里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;
}