HTTP 400 при попытке отправить HTTP Post GraphQL-запрос с использованием HttpClient в Java - PullRequest
0 голосов
/ 08 мая 2018

Иметь пост-запрос для внешнего сервера GraphQL, который работает в настройке Postman Pro в качестве сценария предварительного запроса.

Я пытаюсь подключиться к внешнему серверу GraphQL с помощью HttpClient.

Maven зависимости pom.xml:

<!-- Apache Commons -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.6</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2.5</version>
</dependency>

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.6</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore</artifactId>
    <version>4.2.4</version>
</dependency>

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.1</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient-cache</artifactId>
    <version>4.2.5</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.2.5</version>
</dependency>

<!-- Google Code -->
<dependency>
    <groupId>com.googlecode.json-simple</groupId>
    <artifactId>json-simple</artifactId>
    <version>1.1.1</version>
</dependency>

Сценарий предварительного запроса жестко закодирован следующим образом:

GetDataAsRequest.java

public class GetDataAsRequest {
    private static final String GET_DATA_REQUEST_TEMPLATE = 
    "query {" 
        + "    viewer {     "
        + "        data(id: \"10045701-2017-41a4-33f4-bf8481cf01dc\") {" + 
        "            id"
        + "            createdDate" 
        + "            lastModifiedDate" 
        + "            abbreviation"
        + "            cityStateRegion" 
        + "        }"
        + "    }"
        + "}";
    }

    public static String generateQuery() {
        return String.format(GET_DATA_REQUEST_TEMPLATE);
    }
}

MyController:

public class MyController {

    private static final String EXTERNAL_API_URL = "https://sample-api.com"

    public static void main (String args []) {

        // Generate Access Token
        String accessToken = OAuth2Client.generateAccessToken();
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest = new HttpPost(EXTERNAL_API_URL);
        StringEntity postBody = new StringEntity(GetDataAsRequest.generateQuery());
        postBody.setContentType("application/json");
        postRequest.addHeader("Authorization", "Bearer " + accessToken);
        postRequest.setEntity(postBody);
        HttpResponse response = httpClient.execute(postRequest);

        if (response.getStatusLine().getStatusCode() != 201) {
            throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
        }

        BufferedReader br = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));

        String output;
        System.out.println("Output from Server .... \n");
        while ((output = br.readLine()) != null) {
            System.out.println(output);
        }
        httpClient.getConnectionManager().shutdown();
        } 
        catch (MalformedURLException e) {
            e.printStackTrace();
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
    }

Хотя тот же OAuthToken и HTTP-пост-запрос работают, когда я копирую его из stdin (console) в вызов Postman, я продолжаю получать HTTP 400 при попытке эмулировать тот же вызов с использованием HttpClient внутри Java-программы:

03:25:30.690 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Get connection for route {s}->https://https://sample-api.com
03:25:30.751 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnectionOperator - Connecting to https://sample-api.com:443
03:25:30.943 [main] DEBUG org.apache.http.client.protocol.RequestAddCookies - CookieSpec selected: best-match
03:25:30.950 [main] DEBUG org.apache.http.client.protocol.RequestAuthCache - Auth cache not set in the context
03:25:30.950 [main] DEBUG org.apache.http.client.protocol.RequestTargetAuthentication - Target auth state: UNCHALLENGED
03:25:30.951 [main] DEBUG org.apache.http.client.protocol.RequestProxyAuthentication - Proxy auth state: UNCHALLENGED
03:25:30.951 [main] DEBUG org.apache.http.impl.client.DefaultHttpClient - Attempt 1 to execute request
03:25:30.951 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection - Sending request: POST /v1/oauth/token HTTP/1.1
03:25:30.951 [main] DEBUG org.apache.http.wire - >> "POST /v1/oauth/token HTTP/1.1[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "Content-Length: 119[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "Content-Type: application/x-www-form-urlencoded; charset=UTF-8[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "Host: https://sample-api.com[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "Connection: Keep-Alive[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "User-Agent: Apache-HttpClient/4.2.5 (java 1.5)[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.wire - >> "[\r][\n]"
03:25:30.952 [main] DEBUG org.apache.http.headers - >> POST /v1/oauth/token HTTP/1.1
03:25:30.952 [main] DEBUG org.apache.http.headers - >> Content-Length: 119
03:25:30.952 [main] DEBUG org.apache.http.headers - >> Content-Type: application/x-www-form-urlencoded; charset=UTF-8
03:25:30.952 [main] DEBUG org.apache.http.headers - >> Host: https://sample-api.com
03:25:30.952 [main] DEBUG org.apache.http.headers - >> Connection: Keep-Alive
03:25:30.953 [main] DEBUG org.apache.http.headers - >> User-Agent: Apache-HttpClient/4.2.5 (java 1.5)
03:25:30.953 [main] DEBUG org.apache.http.wire - >> "grant_type=client_credentials&client_id=fghuXeULFBdW4B1dmRY0MhROMRQnlumk&client_secret=MM2banXEq2R1GhRvIQ2d2AKRx0SORvb4"
03:25:31.132 [main] DEBUG org.apache.http.wire - << "HTTP/1.1 200 OK[\r][\n]"
03:25:31.134 [main] DEBUG org.apache.http.wire - << "X-Application-Context: application:prod[\r][\n]"
03:25:31.134 [main] DEBUG org.apache.http.wire - << "Content-Type: application/json[\r][\n]"
03:25:31.134 [main] DEBUG org.apache.http.wire - << "Cache-Control: no-store[\r][\n]"
03:25:31.134 [main] DEBUG org.apache.http.wire - << "Pragma: no-cache[\r][\n]"
03:25:31.134 [main] DEBUG org.apache.http.wire - << "Accept-Ranges: bytes[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "X-Cache-Hits: 0[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "X-Timer: S1525774921.421988,VS0,VE41[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Date: Tue, 08 May 2018 10:22:01 GMT[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Content-Length: 325[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Connection: keep-alive[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "X-Sample-APP: sso[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Access-Control-Allow-Headers: Authorization,Content-Type[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Access-Control-Allow-Methods: PUT,POST,OPTIONS,GET,PATCH,DELETE[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "Access-Control-Allow-Origin: *[\r][\n]"
03:25:31.135 [main] DEBUG org.apache.http.wire - << "[\r][\n]"
03:25:31.136 [main] DEBUG org.apache.http.impl.conn.DefaultClientConnection - Receiving response: HTTP/1.1 200 OK
03:25:31.136 [main] DEBUG org.apache.http.headers - << HTTP/1.1 200 OK
03:25:31.136 [main] DEBUG org.apache.http.headers - << X-Application-Context: application:prod
03:25:31.136 [main] DEBUG org.apache.http.headers - << Content-Type: application/json
03:25:31.136 [main] DEBUG org.apache.http.headers - << Cache-Control: no-store
03:25:31.136 [main] DEBUG org.apache.http.headers - << Pragma: no-cache
03:25:31.138 [main] DEBUG org.apache.http.headers - << Accept-Ranges: bytes
03:25:31.138 [main] DEBUG org.apache.http.headers - << X-Served-By: cache-sample-las9320
03:25:31.138 [main] DEBUG org.apache.http.headers - << X-Cache-Hits: 0
03:25:31.138 [main] DEBUG org.apache.http.headers - << X-Timer: S1525774921.421988,VS0,VE41
03:25:31.138 [main] DEBUG org.apache.http.headers - << Date: Tue, 08 May 2018 10:22:01 GMT
03:25:31.138 [main] DEBUG org.apache.http.headers - << Content-Length: 325
03:25:31.138 [main] DEBUG org.apache.http.headers - << Connection: keep-alive
03:25:31.138 [main] DEBUG org.apache.http.headers - << X-Sample-APP: sso
03:25:31.138 [main] DEBUG org.apache.http.headers - << Access-Control-Allow-Headers: Authorization,Content-Type
03:25:31.138 [main] DEBUG org.apache.http.headers - << Access-Control-Allow-Methods: PUT,POST,OPTIONS,GET,PATCH,DELETE
03:25:31.138 [main] DEBUG org.apache.http.headers - << Access-Control-Allow-Origin: *
03:25:31.141 [main] DEBUG org.apache.http.impl.client.DefaultHttpClient - Connection can be kept alive indefinitely
03:25:31.147 [main] DEBUG org.apache.http.wire - << "{"access_token":"fkMmGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6bnVsbCwiZGV2aWNlSWQiOm51bGwsImNsaWVudElkIjoiaUxIdVhlVUxGQmRXNEIxZG1SWTBNaFJPTVJRbmxmZUsiLCJhZElkIjpudWxsLCJleHAiOjE1MjU3Nzg1MjEsImlhdCI6MTUyNTc3NDkyMX0.U3gacgf7a8hlwCuCn6yGXc0z6E5Zrwgii3B_77xFlyo","token_type":"Bearer","expires_in":3600,"refresh_token":null,"scope":null}"
03:25:31.147 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl@2ddc8ecb
03:25:31.147 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Connection can be kept alive indefinitely
Exception in thread "main" java.lang.RuntimeException: Failed : HTTP error code : 400

Возвращает ли это HTTP 400, потому что мое тело запроса каким-то образом неверно?

Существует ли более простой способ получения ответов JSON с помощью библиотек Java GraphQL:

<!-- GraphQL -->
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java</artifactId>
    <version>8.0</version>
</dependency>

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-tools</artifactId>
    <version>5.0.0</version>
</dependency>

Многие примеры в Интернете показывают, как настроить внешний сервер GraphQL, и мне нужно научиться использовать Java-библиотеки GraphQL, служащие в качестве клиентской библиотеки, для анализа и получения правильного ответа GraphQL от внешнего сервера. ..

Это корректно возвращается из Postman Pro и curl, но без использования HttpClient.

Что я, возможно, делаю не так?

1 Ответ

0 голосов
/ 13 мая 2018

Вы управляете сервером? Если так, то почему бы не поставить точку останова и проверить, что не работает? Если вы не контролируете сервер, я бы сказал, дважды проверьте различия между тем, что вы отправляете здесь, и почтальоном.

Одна вещь выглядит очень подозрительно сразу. Вы отправляете POST, который утверждает, что имеет тело JSON, но отправляемая строка представляет собой необработанный запрос GraphQL, а не JSON вообще.

Я мог бы сказать вам, чтобы превратить тело запроса в объект JSON, как определено в GraphQL через HTTP Spec , но не зная, реализует ли ваш сервер эту спецификацию, это всего лишь предположение.

Спецификация определяет правильное тело запроса POST - это объект JSON с 3 полями: query, operationName и variables. Поле query должно содержать запрос string (поэтому сначала приведите в порядок запрос), operationName содержит имя операции, которую нужно выполнить в случае нескольких (не относится к вашему случаю), и variables содержит объект JSON с переменными в виде пар ключ-значение (сейчас не актуально).

То есть в вашем случае тело должно выглядеть так:

{
    query: "{
        viewer {
            data(id: \"10045701-2017-41a4-33f4-bf8481cf01dc\") {
                id
                createdDate
                lastModifiedDate
                abbreviation
                cityStateRegion
            }
        }
    }"
}

Чтобы поместить эту строку в код Java, все это требует дополнительный уровень экранирования , но я надеюсь, что ваша IDE позаботится об этом. Также обратите внимание, что разрывы строк важны. Если вы потеряете их по какой-либо причине, вы должны поставить запятые между выбранными полями, чтобы запрос оставался действительным.

...