Retrofit ошибка 400

This is the function which i used for the network calls.

private void getSample() {


    Log.d("", "getSample : ");
    OkHttpClient client = new OkHttpClient();

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    client.interceptors().add(interceptor);

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(NetworkCalls.BASE_URL)
            .client(client)

            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    NetworkCalls.CustomerApi customerApi = retrofit.create(NetworkCalls.CustomerApi.class);

    Log.e("customerApi  Created", "customerApi object Created : ");

    customerApi.getCategories("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjgsImlzcyI6Imh0dHA6XC9cLzE5Mi4xNjguMS42MDo4ODg4XC9DQ1YzXC9wdWJsaWNcL2FwaVwvbG9naW4iLCJpYXQiOjE0NDk0ODg5NDMsImV4cCI6MTQ0OTQ5MjU0MywibmJmIjoxNDQ5NDg4OTQzLCJqdGkiOiI0ODY4ZmNmZDk4OTIxZGQwYjA2ZDZlN2EyYjRjZGMxMSJ9.7c60LRQMFCtqprCbbULgR5xG-FxwXnRUZPuWeMJXcNE")
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Response<DataCategoryList>>() {
                @Override
                public void onCompleted() {

                    Log.e("onCompleted", "onCompleted : ");

                }

                @Override
                public void onError(Throwable e) {
                    Log.e("onError", "onError : " + e.getMessage());
                    e.printStackTrace();

                    // network errors, e. g. UnknownHostException, will end up here
                }

                @Override
                public void onNext(Response<DataCategoryList> startupResponseResponse) {



                }
            });
}

Interface class

public interface CustomerApi {
    @Headers({
            "Accept: application/json"
    })
    @FormUrlEncoded
    @POST("categories")
    Observable<Response<DataCategoryList>> getCategories(@Field("token") String token);

    }

getting 400 Bad Request.

Error log

  <-- HTTP/1.1 400 Bad Request (207ms)
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Date: Mon, 07 Dec 2015 12:19:22 GMT
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Server: Apache/2.2.29 (Unix) mod_wsgi/3.5 Python/2.7.10 PHP/5.6.10 mod_ssl/2.2.29 OpenSSL/0.9.8zg DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.22.0
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: X-Powered-By: PHP/5.6.10
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Cache-Control: no-cache
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Set-Cookie: XSRF-TOKEN=5Uqd6WSjbalLcvX3o9RLDY1bGt69ktNoiLZZOahP; expires=Mon, 07-Dec-2015 14:19:22 GMT; Max-Age=7200; path=/
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Set-Cookie: laravel_session=882b5bdedd5dac0fcbfb88706406e3cc0acf91f6; expires=Mon, 07-Dec-2015 14:19:22 GMT; Max-Age=7200; path=/; httponly
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Content-Length: 30
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Connection: close
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: Content-Type: application/json
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: OkHttp-Selected-Protocol: http/1.1
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: OkHttp-Sent-Millis: 1449490736233
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: OkHttp-Received-Millis: 1449490736410
  12-07 17:48:56.408 21024-21067/com.cc.customer D/OkHttp: <-- END HTTP (30-byte body)

Any help would be really appreciated.

asked Dec 7, 2015 at 12:31

Murali Ganesan's user avatar

Murali GanesanMurali Ganesan

2,9254 gold badges20 silver badges31 bronze badges

0

400 sounds like the specific error code that you are getting from your server.
You can try debugging by adding loglevel on Retrofit.

OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addInterceptor(loggingInterceptor);

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(NetworkCalls.BASE_URL)
        .client(clientBuilder.build())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build();

add dependencies to gradle

compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'

With the loglevel, you can possibly see some error json back from your server.

Example:

 {"statusCode":400,"message":"Some parameters are missing"}
 D/Retrofit: <--- END HTTP (76-byte body)

answered Dec 7, 2015 at 22:04

Emma's user avatar

0

I solve my problem after sending data in Map. its work for me.

     Map<String,String> hashMap=new HashMap<>();
    hashMap.put("client_id","2");
    hashMap.put("client_secret",Constant.CLIENT_SECRET);
    hashMap.put("grant_type",Constant.GRANT_TYPE);
    hashMap.put("username",et_user.getText.toString();
    hashMap.put("password",etpassword.getText().toString());
    Call<LoginDataModel> call=apiInterface.login(hashMap);

And in ApiInterface Just i have add a method like this

 @FormUrlEncoded
@POST("oauth/token")
Call<LoginDataModel> login(@FieldMap Map<String, String> options);

answered Jun 6, 2018 at 7:10

sanjeev kumar's user avatar

0

To handle 400 Bad Request error in response use following code.

         if (response.isSuccessful()) {
            if (response.body().getStatus().equals(1)) {
                progressBar.setVisibility(View.GONE);
                Toast.makeText(UploadPDFActivity.this, "Success", 
        Toast.LENGTH_SHORT).show();
            }
        } else {
            int statusCode = response.code();
            Log.e("hello 4001", "else condition");

            if (statusCode == 400) {
                progressBar.setVisibility(View.GONE);
                if (!response.isSuccessful()) {
                    JSONObject jsonObject = null;
                    try {
                        jsonObject = new JSONObject(response.errorBody().string());
                        String entityId = jsonObject.getString("entity_id");
                        String errorMessage = jsonObject.getString("message");
                        String errorStatus = jsonObject.getString("status");
                        Log.e("hello entityId", entityId);
                        Log.e("hello errorMessage", errorMessage);
                        Log.e("hello errorStatus", errorStatus);
                        Toast.makeText(UploadPDFActivity.this, errorMessage, Toast.LENGTH_SHORT).show();

                    } catch (JSONException | IOException e) {
                        e.printStackTrace();
                    }
                }

                 }
                  else {
                // Handle other error cases
            }
        }
    }

answered Aug 29 at 9:48

Rakesh Jha's user avatar

Rakesh JhaRakesh Jha

2792 silver badges7 bronze badges

I am having a strange issue over here. My PATCH and POST Retrofit methods return 400 error, even before coming to server side, when mobile data connection is on. When I turn WI-Fi on, everything works fine.

       restAdapter = makeDefaultBuilder(baseURL).setRequestInterceptor(new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
               // setup headers
            }
        }).build();

where makeDefaultBuilder is:

private RestAdapter.Builder makeDefaultBuilder(String baseURL) {
    OkHttpClient okHttpClient = new OkHttpClient();
    okHttpClient.setReadTimeout(READ_TIMEOUT, TimeUnit.SECONDS);
    okHttpClient.setConnectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS);

    return new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.BASIC)
            .setEndpoint(baseURL)
            .setClient(new OkClient(okHttpClient))
            .setErrorHandler(new APIErrorHandler(context));
}

Here is the log:

01-28 10:26:15.919    9769-9796/com.example D/Retrofit﹕ ---> HTTP PATCH     http://example.com/api/v1/endpoint
01-28 10:26:15.919    9769-9796/com.example D/Retrofit﹕ Cache-Control: no-cache
01-28 10:26:15.919    9769-9796/com.example D/Retrofit﹕ Content-Type: application/json; charset=UTF-8
01-28 10:26:15.919    9769-9796/com.example D/Retrofit﹕ Content-Length: 245
01-28 10:26:15.920    9769-9796/com.example D/Retrofit﹕ {"settings":{"settings_1":true,"settings_2":true}}
01-28 10:26:15.920    9769-9796/com.example D/Retrofit﹕ ---> END HTTP (245-byte body)
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ <--- HTTP 400 http://example.com/api/v1/endpoint (1103ms)
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ : HTTP/1.0 400 Bad request
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ Connection: close
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ Content-Type: text/plain
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ Date: Wed Jan 28 09:26:17 2015
01-28 10:26:17.023    9769-9796/com.example D/Retrofit﹕ OkHttp-Received-Millis: 1422437177022
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ OkHttp-Response-Source: NETWORK 400
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ OkHttp-Selected-Protocol: http/1.0
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ OkHttp-Sent-Millis: 1422437176962
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ Server:
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ Request could not be understood( Status: 400 )
01-28 10:26:17.024    9769-9796/com.example D/Retrofit﹕ <--- END HTTP (46-byte body)
01-28 10:26:17.025    9769-9796/com.example E/APIErrorHandler﹕ Endpoint Error. StatusCode: 400, Error: API Changed Something, response: Request could not be understood( Status: 400 )

This request never make to server side. I tried setting headers Cache-control: no-cache, setting .setCache(null) on OkHttpClient (I had a thought that maybe request is cached).

When I try this request using Postman, or from terminal using curl everything is ok, and I do get response back.

I also tried to wrap a client in new class, and to check connectivity issues before making requests (thinking maybe there is no connectivity because it’s on mobile data connection) but this did not help either.

Any more ideas? Thanks in advance.

Поэтому, когда я вызываю вызов API POST на мой сервер, я получаю ошибку 400 Bad Request с ответом JSON.

{
    "userMessage": "Blah",
    "internalMessage": "Bad Request blah blah",
    "errorCode": 1
}

Я называю это

Call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //AA
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        //BB
    }
}

Однако проблема заключается в том, что как только я получаю ответ, onFailure() вызывается так, что вызывается //BB. Здесь у меня нет доступа к ответу JSON.
Когда я регистрирую запрос и ответ api, он вообще не показывает ответ JSON. И Throwable t — это исключение IOException. Однако, как ни странно, когда я делаю тот же вызов в Postman, он возвращает ожидаемый ответ JSON с 400 кодом ошибки.

Итак, мой вопрос: как я могу получить ответ json, когда я получаю ошибку 400 Bad Request? Должен ли я добавить что-то к okhttpclient?

Спасибо

Поделиться

Источник

6 ответов

Вы можете сделать это как в своем методе onResponse, помните, что 400 — это статус ответа, а не ошибка:

if (response.code() == 400) {              
    Log.v("Error code 400",response.errorBody().string());
}

И вы можете обрабатывать любой код ответа кроме 200-300 с помощью Gson, например:

if (response.code() == 400) {
   Gson gson = new GsonBuilder().create();
   ErrorPojoClass mError=new ErrorPojoClass();
   try {
         mError= gson.fromJson(response.errorBody().string(),ErrorPojoClass .class);
         Toast.makeText(getApplicationContext(), mError.getErrorDescription(), Toast.LENGTH_LONG).show();
        } catch (IOException e) {
           // handle failure to read error
        }        
}

Добавьте это в свой build.gradle: compile 'com.google.code.gson:gson:2.7'

Если вы хотите создать класс Pojo, перейдите в Json Schema 2 Pojo и вставьте свой пример ответа Json. Выберите тип источника Json и аннотация Gson.

Yasin Kaçmaz

Поделиться

Вы можете попробовать следующий код, чтобы получить 400 ответов. Вы можете получить ответ об ошибке из метода errorBody().

Call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        //get success and error response here
 if (response.code() == 400) {
                if(!response.isSuccessful()) {
                    JSONObject jsonObject = null;
                    try {
                        jsonObject = new JSONObject(response.errorBody().string());
                        String userMessage = jsonObject.getString("userMessage");
                        String internalMessage = jsonObject.getString("internalMessage");
                        String errorCode = jsonObject.getString("errorCode");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        //get failure response here
    }
}
}

РЕДАКТИРОВАТЬ: Исправлено имя метода из toString в string

Sathish Kumar VG

Поделиться

У меня была аналогичная проблема, но существующий код придерживался сети RxJava 2.
Здесь мое решение:

   public static <T> Observable<T> rxified(final Call<T> request, final Class<T> klazz) {
    return Observable.create(new ObservableOnSubscribe<T>() {

        AtomicBoolean justDisposed = new AtomicBoolean(false);

        @Override
        public void subscribe(final ObservableEmitter<T> emitter) throws Exception {

            emitter.setDisposable(new Disposable() {
                @Override
                public void dispose() {
                    request.cancel();
                    justDisposed.set(true);
                }

                @Override
                public boolean isDisposed() {
                    return justDisposed.get();
                }
            });

            if (!emitter.isDisposed())
                request.enqueue(new Callback<T>() {
                    @Override
                    public void onResponse(Call<T> call, retrofit2.Response<T> response) {
                        if (!emitter.isDisposed()) {
                            if (response.isSuccessful()) {
                                emitter.onNext(response.body());
                                emitter.onComplete();

                            } else {
                                Gson gson = new Gson();
                                try {
                                    T errorResponse = gson.fromJson(response.errorBody().string(), klazz);
                                    emitter.onNext(errorResponse);
                                    emitter.onComplete();
                                } catch (IOException e) {
                                    emitter.onError(e);
                                }
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<T> call, Throwable t) {
                        if (!emitter.isDisposed()) emitter.onError(t);
                    }
                });
        }
    });
}

Преобразование 400-подобных ответов в цепочку rx довольно просто:

Call<Cat> request = catApi.getCat();
rxified(request, Cat.class).subscribe( (cat) -> println(cat) );

Lukas

Поделиться

public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
    DialogHelper.dismiss();

    if (response.isSuccessful()) {
        // Success
    } else {
        try {
            JSONObject jObjError = new JSONObject(response.errorBody().string());
            Toast.makeText(getContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
}

Keshav Gera

Поделиться

Первый шаг:

Создайте свой класс POJO для ответа об ошибке. В моем случае ApiError.java

public class ApiError {

    @SerializedName("errorMessage")
    @Expose
    private String errorMessage;

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage= errorMessage;
    }
}

Второй шаг:

Напишите ниже код в вашем обратном вызове API.

Call.enqueue(new Callback<RegistrationResponse>() {
     @Override
     public void onResponse(Call<RegistrationResponse> call, Response<RegistrationResponse> response) 
     {
         if (response.isSuccessful()) {
             // do your code here
         } else if (response.code() == 400) {
             Converter<ResponseBody, ApiError> converter =
                            ApiClient.retrofit.responseBodyConverter(ApiError.class, new Annotation[0]);

                    ApiError error;

                    try {
                        error = converter.convert(response.errorBody());
                        Log.e("error message", error.getErrorMessage());
                        Toast.makeText(context, error.getErrorMessage(), Toast.LENGTH_LONG).show();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
         }
     }

     @Override
     public void onFailure(Call<RegistrationResponse> call, Throwable t) {
         //do your failure handling code here
     }
}

Здесь ApiClient.retrofit — это ваш экземпляр модернизации, который является статическим.

Ekta Bhawsar

Поделиться

Вот как вы можете обрабатывать ответное сообщение
Я обрабатываю ошибку 500, вы можете добавить столько, сколько хотите.

                switch (response.code()) {
                    case HttpURLConnection.HTTP_OK:
                        break;
                    case HttpURLConnection.HTTP_UNAUTHORIZED:
                        callback.onUnAuthentic();
                        break;
                    case HttpURLConnection.HTTP_INTERNAL_ERROR:
                        try {
                            String errorResponse = response.errorBody().string();
                            JSONObject object = new JSONObject(errorResponse);
                            String message = "Error";
                            if (object.has("Message"))
                                message = String.valueOf(object.get("Message"));
                            callback.onError(message);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
                    case HttpURLConnection.HTTP_CLIENT_TIMEOUT:
                    default:
                        callback.onNetworkError();
                        break;
                }

Shivam Mathur

Поделиться

Ещё вопросы

  • 0Компиляция библиотек Boost C ++ в проекте VS2012
  • 1SSL не работает на Android 2.2 (только в 2.3)
  • 1UserControl Fire Событие при изменении свойства
  • 0Сохранить файл PDF на сервер
  • 0Метод uploadStoredFiles не существует в jQuery.fineUploader
  • 0происхождение функции javascript [дубликаты]
  • 0TypeError: window.parent.updatepic не является функцией, когда я пытаюсь получить доступ к функции из iframe к родителю его окна
  • 0одно и то же слово добавлено дважды [копия]
  • 0`const char * ‘to` char’
  • 0MySQL: как отсортировать некоторые записи в ASC, а некоторые в порядке DESC, основываясь на значении другого поля
  • 0Internet Explorer Print Issue
  • 0Проверьте, отрицательно ли значение более чем в 5 раз, и отметьте их
  • 0jQuery — ошибка перетаскиваемого элемента в стиле html + возврат в оригинальный контейнер
  • 1Eclipse IDE ошибка компиляции
  • 0MySQL: возможно ли ПОЛУЧИТЬ ПОЛЕ в ОБНОВЛЕНИИ?
  • 0Как вычесть количество моих продуктов, перечисленных в списке, непосредственно в мою базу данных продуктов? (Баз данных)
  • 0Получение MySQLSyntaxErrorException с Hibernate Spatial и MySQL 5.6
  • 0Отправлять почту всякий раз, когда журнал очищается в Magento
  • 1Как работают функции Python SimpleHTTPServer do_GET и do_POST?
  • 1Ошибка входа в GooglePlayServices для игры Unity
  • 0SQL — вставка новой строки зависит от предыдущих данных из той же таблицы
  • 0Программа останавливается при вызове конструктора, c ++
  • 0Класс элемента не отражается после append ()
  • 1Поиск не является ошибкой функции
  • 1Java-код для отображения цикла
  • 1Недостижимая проблема с блоком Catch
  • 0jquery / Regex, остановка событий
  • 0как сохранить промежуточный итог 2d массива
  • 0Как отобразить значения массива PHP в Google Charts на основе JS?
  • 1Почему TextReader жалуется, когда файл открывается другим процессом?
  • 1Как использовать анимацию поворота при перетаскивании вида, чтобы центральное положение постоянно менялось? Решить вопрос от степени к степени
  • 1Возможно ли, что getInstallerPackageName () имеет значение null, когда приложение загружено из Google Play Store?
  • 1Pandas_Merge два больших набора данных
  • 1Удаление одинаковых выбросов в двух временных сериях
  • 1Внедрение зависимостей только для базовой активности приводит к сбою дочерней активности
  • 1Arduino мигает светодиод на нажатой кнопке приложения c #
  • 0Встроенный Boost-Spirit-Lex для придания токенам имени строки?
  • 0C ++ Статическая Декларация
  • 1Несколько модалов не будут закрываться при нажатии за пределами
  • 1Grails не кодирует в UTF-8 после публикации тела с помощью contentType application / json
  • 1Невозможно получить какой-либо ответ от API (залп)
  • 1Как обрабатывать большой размер ввода в Java?
  • 1JSON должен быть загружен в фоновом режиме?
  • 1Jade / мопс выберите форму Javascript Onchange событие
  • 1Есть ли в Java контейнер с постоянным временем / журналом и постоянным доступом / журналом по времени индекса?
  • 0Как я могу предотвратить ссылку, чтобы отправить меня в начало страницы
  • 1Как начать потоковое видео с помощью webRTC?
  • 0JQuery: как вызвать функцию через строку в классе
  • 1Сохранение порядка имен столбцов to_dict
  • 0Измените php, если файл не содержит слова

Сообщество Overcoder

Introduction

Retrofit is a popular library used to make HTTP requests in Android applications. However, sometimes you may encounter the Retrofit 400 Bad Request error when making API requests using this library. This error signals that the server cannot understand the client’s request due to incorrect or poorly-constructed syntax.

This article aims to provide tips and tricks for overcoming the Retrofit 400 Bad Request error.

Common Causes of Retrofit 400 Bad Request Error

  1. Incorrect Parameter Types: Ensure that the types of the parameters passed in the request match the definition in the API endpoint.

  2. Incorrect URL: Ensure that the API endpoint URL is correct and valid.

  3. Incomplete Request Body: Ensure that the request body is complete and all required parameters are present.

  4. Improper RESTful Call Format: Ensure that the call format is correct such as POST, GET, PUT, etc.

If none of these are the cause of the error, consider the tips below for resolving the error.

Tips and Tricks for Overcoming the Retrofit 400 Bad Request Error

Tip 1: Log the Error Response

One of the essential tools to overcoming the Retrofit 400 Bad Request Error is by logging the error response while making the request. To do this, add an interceptor to your Retrofit instance and log the response. You can then read through the response details to identify the error source and resolve it.

Here is an example of a log statement:

D/Retrofit: HTTP 400 Bad Request

Tip 2: Debug with Postman

Postman is an HTTP client application that allows you to test APIs by making requests to them. You can use Postman to test the API endpoint and compare the result with what you get in the app. If the API endpoint works correctly in Postman, then the error is likely in your app code.

Tip 3: Update Dependencies

Retrofit releases updates often to manage errors. Updating the library to the latest version can resolve the Retrofit 400 Bad Request Error.

Ensure the following dependencies are up to date:

implementation 'com.squareup.retrofit2:retrofit:x.y.z'
implementation 'com.google.code.gson:gson:x.y.z'

Tip 4: Check Your API Documentation

It is crucial to understand the API documentation to make sure your requests match the API criteria. Ensure the API documentation explains what each parameter is, the correct data type, and how to format the data.

Conclusion

Overcoming the Retrofit 400 Bad Request Error can be frustrating, but taking these necessary measures to resolve it can efficiently help. Logging the error response, debugging with Postman, updating dependencies, and checking API documentation can go a long way to save time and reduce frustration.

Problem Description:

So I’m still in the process of learning android dev and I’m currently working on an app which is supposed to show students their grades. Right now I am stuck at getting login to a service from which grades are collected. For that process I am using https://eduo-ocjene-docs.vercel.app/ api (documentation is in Croatian).
This is what curl request for logging in looks like:

curl --location --request GET 'https://ocjene.eduo.help/api/login' --header 'Content-Type: application/json' --data-raw '{    "username":"[email protected]", "password":"ivanovPassword123"}'

Here are screenshots of what I have tried until now

Here is how I build retrofit

object ApiModule {

    private const val BASE_URL = "https://ocjene.eduo.help/"

    lateinit var retrofit: EdnevnikApiService

    private val json = Json { ignoreUnknownKeys = true }

    fun initRetrofit() {
        val okhttp = OkHttpClient.Builder().addInterceptor(HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }).build()

        retrofit = Retrofit.Builder().baseUrl(BASE_URL)
            .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
            .client(okhttp).build().create(EdnevnikApiService::class.java)
    }

}

The login method

interface EdnevnikApiService {

    @HTTP(method = "get", path = "/api/login", hasBody = true)
    fun login(@Body request: LoginRequest): Call<LoginResponse>

}

This is what happens when the login button is clicked

fun onLoginButtonClicked(email: String, password: String) {
    val request = LoginRequest(email, password)
    ApiModule.retrofit.login(request).enqueue(object : Callback<LoginResponse> {
        override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) {
            loginResultLiveData.value = response.isSuccessful
            val body = response.body()
        }

        override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
            loginResultLiveData.value = false
        }

    })
}

and this is what kotlin request and kotlin response data classes look like

@kotlinx.serialization.Serializable
data class LoginRequest(
    @SerialName("username") val username: String,
    @SerialName("password") val password: String,
)
@kotlinx.serialization.Serializable
data class LoginResponse(
    @SerialName("LoginSuccessful") val isSuccessful: Boolean,
)

Oh and this is what I get from the interceptor when I send the request
enter image description here

Solution – 1

My guess is server is responding with 400 Bad Request due to unsupported method type. When I replaced method = "get" with method = "GET" in your sample code, I received:

java.lang.IllegalArgumentException: method GET must not have a request body.

which makes sense. Luckily, the /login API you shared works with POST method type, so you can try using:

@HTTP(method = "POST", path = "/api/login", hasBody = true,)

I checked at my end and I received the following response:

<-- 200 https://ocjene.eduo.help/api/login (1390ms)
access-control-allow-origin: *
access-control-allow-credentials: true
set-cookie: epicCookie=f69fbd6d4f10b5cc38e038b5da0843b356776c58c4fb32aed24dbcc49026778724bc25e21448c05a29df9f4b5558b254011fb3f8a992710f9901f23c53be5eaadaa799f3f5ac9e18de191bed02ef3e96030b83042ee8392755b03dd785edca6a;
content-type: application/json; charset=utf-8
etag: "bkrbkvg0eo6c"
vary: Accept-Encoding
date: Thu, 10 Nov 2022 03:07:08 GMT
server: Fly/b1863e2e7 (2022-11-09)
via: 2 fly.io
fly-request-id: 01GHFR2T56X9K0GFN3DH1Z9JYV-sin
{"LoginSuccessful":false,"token":"f69fbd6d4f10b5cc38e038b5da0843b356776c58c4fb32aed24dbcc49026778724bc25e21448c05a29df9f4b5558b254011fb3f8a992710f9901f23c53be5eaadaa799f3f5ac9e18de191bed02ef3e96030b83042ee8392755b03dd785edca6a"}
<-- END HTTP (228-byte body)

Понравилась статья? Поделить с друзьями:
  • Revloader exe системная ошибка msvcr100 dll
  • Retigo b1011b коды ошибок
  • Revit произошла непоправимая ошибка программа будет закрыта
  • Revision dans перевести ошибка рено
  • Retarder temp ошибка