Android / Kotlin retrofit2.adapter.rxjava2.HttpException: HTTP 415 неподдерживаемый тип носителя - PullRequest
0 голосов
/ 26 июня 2019

Я только начинаю с Retrofit и у меня появляется эта ошибка, когда я просто пытаюсь сделать простой POST request

retrofit2.adapter.rxjava2.HttpException: HTTP 415 неподдерживаемый носитель Тип

Я вообще не знаю, где ошибка.
Я следовал этому учебнику , чтобы реализовать Retrofit и RxJava.

Это мой RetrofitClient, реализующий мой OkHttpClient:

object RetrofitClient {

    private const val CONNECTION_TIMEOUT: Long = 60
    private val BASE_URL = "https://pictalio-dev.azurewebsites.net/api/"

    private var retrofit: Retrofit? = null


    fun getClient(token: String): Retrofit {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(getOkHttpClient(token))
                    .build()
        }
        return retrofit!!
    }

    private fun getOkHttpClient(token: String): OkHttpClient {
        val okClientBuilder = OkHttpClient.Builder()
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        okClientBuilder.addInterceptor { chain ->
            val original = chain.request()

            val requestBuilder = original.newBuilder()
                    .header("Authorization", token)

            val request = requestBuilder.build()
            chain.proceed(request)
        }
        httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC
        okClientBuilder.addInterceptor(httpLoggingInterceptor)
        okClientBuilder.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
        okClientBuilder.readTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
        okClientBuilder.writeTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
        return okClientBuilder.build()
    }
}

Вот мой ApiService:

interface ApiService {
    @FormUrlEncoded
    @POST("account/login")
    fun getUserLogin(
            @Field("email") email: String,
            @Field("password") password: String
    ): Single<User>
}

Вот как я звоню и отношусь к возврату моего запроса:

class SignInActivity : AppCompatActivity(), View.OnClickListener, RequestSignIn.sendDataResponse, RequestGetUser.sendDataResponse {

    private var user: User? = null
    private var pDialog: SweetAlertDialog? = null
    lateinit var emailEditText: EditText
    lateinit var passwordEditText: EditText
    var persistentUser: PersistentUser? = null
    //Initialization of disposable
    private val disposable = CompositeDisposable()

    private lateinit var apiService: ApiService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.signin_activity)

        emailEditText = findViewById(R.id.email)
        passwordEditText = findViewById(R.id.password)
        //Initialization of apiService
        apiService = RetrofitClient.getClient("").create(ApiService::class.java)
    }

    override fun onClick(v: View) {
        val email: EditText
        val password: EditText

        email = findViewById(R.id.email)
        password = findViewById(R.id.password)
            R.id.login -> {
                if (Tools.isValidEmail(email.text.toString())) {
          disposable.add(apiService.getUserLogin(email.text.toString(), password.text.toString())
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe({ user ->
                                pDialog!!.dismissWithAnimation()
                                Log.e("USER", "token: " + user.token)

                            }, Throwable::printStackTrace)
                    )
                } else {
                    Toast.makeText(this@SignInActivity, getString(R.string.enter_valid_email), Toast.LENGTH_SHORT).show()
                    //emailnotvalid
                }
            }
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        disposable.dispose()
    }
}

Буду признателен за любую помощь.

РЕДАКТИРОВАТЬ:
Я удалил @FormUrlEncoded и добавил .header("Content-Type", "application/json")
и теперь я посылаю JSONObject как Body следующим образом:

disposable.add(apiService.getUserLogin(JSONObject(map)))  

Но у меня есть 400 BAD REQUEST с моего сервера.
Я даже добавил ScalarsConverter к своему RetrofitClient.

.addConverterFactory(ScalarsConverterFactory.create())

Итак, я попробовал с RequestBody следующим образом

fun getUserLogin(@Body requestBody: String): Single<User>
disposable.add(apiService.getUserLogin(RequestBody.create(MediaType.parse("application/json"), JSONObject(map).toString())) . 

и это сработало! Как я могу просто отправить JSONObject вместо того, чтобы каждый раз создавать RequestBody?

1 Ответ

1 голос
/ 26 июня 2019

Код состояния 4xx означает, что в запросе, отправленном клиентом, произошла ошибка; в данном конкретном случае 415 означает, что тип содержимого вашего запроса не поддерживается сервером.

Проверяя URL, который вы указали в своем коде, сервер ожидает тип application/json-patch+json MIME, но вместо этого вы предоставляете application/x-www-form-urlencoded (для этого нужна аннотация @FormUrlEncoded).

Чтобы исправить проблему, вы должны изменить метод getUserLogin, чтобы использовать соответствующий Content-Type (см. этот ответ ) и отправить соответствующую полезную нагрузку JSON (см. этот ответ , который также говорит вам, как установить пользовательский заголовок).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...