Android (Java) - POST (с заголовками) с Retrofit 2.1.0

Мне нужно интегрировать RESTful API под названием SMMRY в мое приложение для Android. Этот API-интерфейс выполняет автоматическую текстовую сводку URL-адреса или блока текста, отправляемого на него. Я использую Retrofit 2.1.0 в качестве сетевой библиотеки.

Мне удалось обеспечить идеальное суммирование текста URL, поэтому, когда я передаю URL, он выполняет текстовое резюме и возвращает меня обратно.

Но я не могу правильно реализовать запрос POST, отправив соответствующие параметры (в том числе заголовки и т. Д.), Чтобы он делал сводку блока текста.

Я думаю, что проблема в том, что я неправильно передаю заголовки. Я пробовал 3 разных способа их передачи, но я получаю "нулевое" значение ответа каждый раз. Во-первых, я пытался добавить @Headers перед запросом POST (что я считаю правильным способом); Во-вторых, я попытался передать заголовок в качестве параметра; и наконец, путем управления заголовками запросов в OkHttp Interceptor. Но ничего не работает, или что-то в моем коде не очень хорошо реализовано...

1-страничная документация по API (с примером реализации на PHP): http://smmry.com/api

Ниже приведен полный код (я прокомментировал все способы, которыми я пытаюсь передать заголовки, поэтому легко придумать, какой может быть правильный путь или как мне его исправить):

MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static final String SM_API_KEY= "XXXXXXXXX"; // My API Key (which can be obtained by their site )

    public static final String URL="http://www.abola.pt/nnh/ver.aspx?id=639170";

    public static final String longText= "Robert Catesby (1572?–1605) was the leader of the failed Gunpowder Plot of 1605, " +
            "commemorated in Great Britain every 5 November as Guy Fawkes Night. His family were prominent recusant Catholics." +
            " A letter sent anonymously to William Parker, 4th Baron Monteagle, alerted the authorities, and on the eve of the planned explosion, " +
            "during a search of Parliament, Fawkes was found guarding the barrels of gunpowder, and arrested. Catesby and the remaining plotters made a " +
            "stand against a 200-strong company of armed men at Holbeche House in Staffordshire, where he was shot and killed. As a warning to others, his body" +
            " was exhumed and his head exhibited outside Parliament";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (SM_API_KEY.isEmpty()){
            Log.d("SM_KEY","SM_API_KEY not available");
            return;
        }

        SmmryAPIInterface apiService =
                SmmryAPIClient.getClient().create(SmmryAPIInterface.class);// No headers

        SmmryAPIInterface apiService2 =
                SmmryAPIClient.getClient2().create(SmmryAPIInterface.class); // client with headers, NOT USED RIGHT NOW

        /* Encode the URL when summarizing by URL - which is working OK*/
        String link = null;
        try {
            link = URLEncoder.encode(URL, "utf-8");
        } catch (UnsupportedEncodingException e) {

        }


        // Summary by URL: Working properly, the following commented lines are to call to URL summary ...

        /*Call<SmmaryResponse> call = apiService.getSummaryURL(SM_API_KEY,1,null,null,null,link);
        call.enqueue(new Callback<SmmaryResponse>() {
            @Override
            public void onResponse(Call<SmmaryResponse>call, Response<SmmaryResponse> response) {
                String sm_api_content = String.valueOf(response.body().getSm_api_content());
                //String sm_api_content = response.errorBody().toString();

                Log.e("Resumo", sm_api_content);
            }

            @Override
            public void onFailure(Call<SmmaryResponse>call, Throwable t) {
                // Log error here since request failed
                Log.e("Erro", t.toString());
            }
        });*/


        // Summary by Text : THE PROBLEM IS HERE!:
        String header = "100-continnue";
        Call<SmmaryResponse> call2 = apiService.getSummaryText(SM_API_KEY,
                                                                /*header,*/  // TRIED TO PASS THE HEADER HERE, BUT DID NOT WORK ...
                                                                longText, 2, null, null, null);
        call2.enqueue(new Callback<SmmaryResponse>() {
            @Override
            public void onResponse(Call<SmmaryResponse>call, Response<SmmaryResponse> response) {
                String sm_api_content = String.valueOf(response.body().getSm_api_content());

                Log.e("Summary longText", sm_api_content);
            }

            @Override
            public void onFailure(Call<SmmaryResponse>call, Throwable t) {
                // Log error here since request failed
                Log.e("Erro", t.toString());
            }
        });

    }
}

SmmaryResponse.java

public class SmmaryResponse {
    /*
        Currently in this class I am only using getSm_api_content(), which contains the actual summary ... This is the model class
     */

    private String sm_api_content;

    public SmmaryResponse(String sm_api_content) {
        this.sm_api_content = sm_api_content;
    }

    // the only method I am currently using, to get the summary
    public String getSm_api_content() {
        return sm_api_content;
    }
}

SmmryAPIClient.java

public class SmmryAPIClient {

    /*
      To send network requests to an API, we need to use the Retrofit Builder class and specify the base URL for the service.
     */

    public static final String BASE_URL = "http://api.smmry.com/";

    private static Retrofit retrofit = null;
    private static Retrofit retrofit2 = null;


    /*Method to get the client*/
    public static Retrofit getClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(getRequestHeader())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

    /* Method to set timeout in Retrofit library */
    private static OkHttpClient getRequestHeader() {
        OkHttpClient httpClient = new OkHttpClient.Builder()
                .connectTimeout(100, TimeUnit.SECONDS)
                .writeTimeout(100, TimeUnit.SECONDS)
                .readTimeout(300, TimeUnit.SECONDS)
                .build();
        return httpClient;
    }

    /*The following two methods have the purpose to create client, but this time with Headers */
    public static Retrofit getClient2() {
        if (retrofit2 == null) {
            retrofit2 = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(getRequestHeader2())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit2;
    }

    /* Method to set timeout + headers in Retrofit library */
    private static OkHttpClient getRequestHeader2() {
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request original = chain.request();

                Request request = original.newBuilder()
                        //.addHeader("Content-Type", "text/plain; charset=utf-8")
                        .addHeader("Expect:", "100-continue") //  // TRIED TO PASS THE HEADER HERE, BUT DID NOT WORK ...
                        //.method(original.method(), original.body())
                        .build();
                return chain.proceed(request);
            }
        })
                .connectTimeout(100, TimeUnit.SECONDS)
                .writeTimeout(100, TimeUnit.SECONDS)
                .readTimeout(300, TimeUnit.SECONDS);
        OkHttpClient client = httpClient.build();
        return client;
    }
}

SmmryAPIInterface.java

public interface SmmryAPIInterface {

    /*
    * The following two methods are implemented:
    *   getSummaryURL: method to request for the summary by providing an URL (SM_URL parameter to send URL)
    *   getSummaryText: method to request for the summary by providing a block of text (sm_api_input parameter to send block of text)
    *   Use of any optional parameters provided by Smmry, like SM_LENGTH ,SM_WITH_BREAK, etc is implemented
    */

    /* Pass null value strictly to optional parameters if not needed.*/
    @POST("/")
    Call<SmmaryResponse> getSummaryURL(@Query("SM_API_KEY") String apiKey,
                                       @Query("SM_LENGTH") Integer length,
                                       @Query("SM_WITH_BREAK") Boolean wbreak,
                                       @Query("SM_QUOTE_AVOID") Boolean quote,
                                       @Query("SM_KEYWORD_COUNT") Integer N,
                                       @Query("SM_URL") String urlSite);


    /* Pass null value strictly to optional parameters if not needed.*/

    //@Headers("Expect: 100-continue") // TRIED TO WRITE THE HEADER HERE, BUT DID NOT WORK ...
    @POST("/")
    Call<SmmaryResponse> getSummaryText(@Query("SM_API_KEY") String apiKey,
                                        //@Header("Expect:") String header, // TRIED TO WRITE THE HEADER HERE, BUT DID NOT WORK ...
                                        @Query("sm_api_input") String bText,
                                        @Query("SM_LENGTH") Integer length,
                                        @Query("SM_WITH_BREAK") Boolean wBreak,
                                        @Query("SM_QUOTE_AVOID") Boolean quote,
                                        @Query("SM_KEYWORD_COUNT") Integer N);
}

Я застрял на этом несколько дней и много чего перепробовал, но не понимаю, что я делаю не так. Любая помощь будет оценена. Благодарю.

1 ответ

Решение

На мой взгляд, и первый, и третий варианты верны.

Обратите внимание, что в первом случае, когда вы добавляете только аннотацию @Headers, она добавляется только для одного вызова, но если вы создаете заголовки Interceptor, они будут добавляться во все вызовы, которые используют этот OkHttpClient.

Но я думаю, что ваша проблема в другом месте. Я думаю, что вы неправильно поняли документацию SMMRY. "Sm_api_input" не является параметром запроса.

Пожалуйста, попробуйте следующий код:

@FormUrlEncoded
@POST("/")
Call<SmmaryResponse> getSummaryText(@Query("SM_API_KEY") String apiKey,
                                    @Field("sm_api_input") String bText,
                                    @Query("SM_LENGTH") Integer length,
                                    @Query("SM_WITH_BREAK") Boolean wBreak,
                                    @Query("SM_QUOTE_AVOID") Boolean quote,
                                    @Query("SM_KEYWORD_COUNT") Integer N);

С наилучшими пожеланиями, Марчин

Другие вопросы по тегам