http получить запрос с телом

1

Я знаю, что вы не должны отправлять HTTP GET запрос с телом, но ceilometer web api заставляет меня это делать. Я разрабатываю клиентский сканер ceilometer, поэтому мне нужен способ scala/java для запроса запроса с телом. До сих пор я пробовал с beeClient (http://www.bigbeeconsultants.co.uk) и в простой Java, используя httpConnection, но получаю ошибку 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/

Что мой scala-код, который использует java HttpURLConnection:

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
    Где твой код? Спецификация HTTP ничего не говорит о теле для GET, что означает, что реализации могут решать, хотят ли они разрешить тело для GET или нет. Я считаю, что вы должны быть в состоянии отправить GET с формой тела Java.
  • 0
    Запросы HTTP Get НЕ имеют тела. Так что вы не сможете этого сделать.
Показать ещё 3 комментария
Теги:
http
get

6 ответов

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 также предоставляет API Java NIO.

  • 0
    org.eclipse.jetty.client.HttpClient , как он сравнивается с Apache HttpClient, с ним проще работать
1

Я нашел рабочую простое решение Java здесь, используя апач httpclient, httpcore и commons-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);

Надеюсь, поможет.

1

В общем, спецификация не запрещает тело на любой тип HTTP-запроса (GET, DELETE и т.д.), Поэтому вы можете сделать это, если это необходимо. Однако по соглашению это нетипично.

Проблема, с которой вы сталкиваетесь, заключается в том, что есть предположения о том, что вы можете и чего не можете сделать в реализации URLConnection, которую используете. В общем, вы будете использовать HttpUrlConnection (как вы делаете), который будет фактически реализован вашим jvm. Например, здесь реализована реализация, специфичная для солнца.

Если вы посмотрите на эту реализацию, вы увидите, что предполагается, что запрос GET, в котором вам нужен выходной поток, на самом деле является POST.

Если вы хотите GET с телом, вам нужно использовать другой метод подключения, например, такую библиотеку, как apache-http-client. Вы можете начать с рассмотрения этого вопроса. Для вас могут быть лучшие альтернативы scala.

1

Вы используете запрос HTTP PUT или POST при отправке тела запроса для Celiometer API.

Я проверил документацию Ceilometer и обнаружил, что все запросы с телом запроса используют методы HTTP PUT или POST. Нет метода GET с телом запроса. http://docs.openstack.org/developer/ceilometer/webapi/v2.html

  • 0
    False: посмотрите последнюю команду curl в этом разделе: docs.openstack.org/developer/ceilometer/webapi/…
  • 0
    Я понимаю вашу точку зрения. Однако все же это позволяет вам использовать параметр URL в запросе GET. > «Параметры запроса должны быть закодированы с использованием одного из указанных выше методов, например, в качестве параметров URL или в виде данных в кодировке JSON, переданных в запрос GET.»
Показать ещё 2 комментария
0

вы также можете попробовать

@RequestMapping (value = "/listcategories", метод = RequestMethod.GET)

private ModelAndView getCategories() {
    ModelAndView modelAndView = new ModelAndView("list-of-categories");
    List<Category> categories = categoryService.getAllCategories();
    modelAndView.addObject("categories", categories);
    return modelAndView;
}
  • 1
    Я думаю, что вы ответили не на тот вопрос! ;)
0

После проверки документации 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. Если у вас есть определенная причина не использовать параметры URL для вашего подхода JSON, я думаю, что кодирование - это то, что отсутствует в вашем запросе. Параметры должны быть отправлены только в параметрах запроса, а не в содержании тела. Для этого я предполагаю, что вам нужно попробовать с приведенными ниже закодированными данными, как показано ниже, на основе вашего запроса в вопросе.

    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 - имя параметра корневого запроса, без токена, я не смог его проверить.

Замените YOURHOST.COM ip-адресом для вашего сервера, поскольку он показывал мне проблемы даже после помещения их в блок кода и, пожалуйста, дайте мне знать.

  • 0
    Я уже пытался передать JSON в качестве параметра запроса, но это не работает. Я решил проблему передачи json, закодированного в теле запроса GET, используя клиент Jetty. Я не смог добиться этого в простой Java из-за реализации HttpURLConnection, которая не обеспечивает эту функциональность.
  • 0
    Таким образом, использование Jetty Client приемлемо в вашем случае? Можете ли вы поделиться своим кодом здесь Jetty Client?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню