Запрос PUT с Retrofit не проходит, но curl проходит - PullRequest
3 голосов
/ 18 июня 2020

Я хочу отправить запрос PUT из приложения Android с Retrofit для моего Flask API, который должен обновить документ MongoDB. Выполнение команды curl со всем URL-адресом работает нормально, но при запуске функции модернизации ничего не происходит.

Просматривая журналы с сервера, я вижу все мои запросы GET, но не мой запрос PUT.

flask            | [2020-06-18 19:07:16 +0000] [19] [DEBUG] GET /beers/all
flask            | [2020-06-18 19:07:30 +0000] [20] [DEBUG] GET /beers/by_barcode
flask            | [2020-06-18 19:07:30 +0000] [10] [DEBUG] GET /beers/by_id

Когда я использую эту команду curl

curl -X PUT 'http://0.0.0.0:5000/users/add_scanned?user_id=test2&beer_id=test2C&beer_name=test2&img_link=http://test2'

все работает, как ожидалось, и я вижу эти журналы:

flask            | [2020-06-18 19:26:49 +0000] [11] [DEBUG] PUT /users/add_scanned
flask            | [2020-06-18 19:26:49 +0000] [11] [INFO] Adding beer scanned

Mon go doesn ' не записывать что-нибудь странное. Другой запрос PUT с Retrofit работает как шарм.

flask            | [2020-06-18 19:10:38 +0000] [20] [DEBUG] PUT /beers/update_barcode

Вот мой код.

Android Retrofit API

import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Query


private const val BASE_URL = "http://***.***.**.*:5000/"

private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(ScalarsConverterFactory.create())
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(BASE_URL)
    .build()

interface UserApiService {

    /**
     * Adds a beer to scanned list
     */
    @PUT("users/add_scanned")
    fun addScanned(
        @Query("user_id") userId: String,
        @Query("beer_id") beerId: String,
        @Query("beer_name") beerName: String
        ):
            Call<String>
    }

Flask Чертеж

from flask import Blueprint, jsonify, request, abort
from bson.objectid import ObjectId
from pymongo import MongoClient
from flask import current_app

bp = Blueprint('users', __name__, url_prefix='/users')
client = MongoClient(host="mongo", username="*****", password="*****")
db = client.TeddyMongo
collection = db.users

def to_dict(document):
    document["_id"] = str(document["_id"])
    return document

# When a user is not found
@bp.errorhandler(404)
def user_not_found(e):
    return jsonify(error=str(e)), 404

# Add beer scanned
@bp.route('/add_scanned', methods=['PUT'])
def add_scanned():
    user_id = request.args.get('user_id')

    scanned = {
        "_id" : request.args.get('beer_id'),
        "name" : request.args.get('beer_name')
    }

    if request.args.get('img_link'):
        scanned["img_link"] = request.args.get('img_link')

    current_app.logger.info("Adding beer scanned")

    collection.update_one({"_id":user_id}, { "$addToSet" : {"scanned" : scanned}}, upsert=True)

    return "Beer added to scanned"

1 Ответ

1 голос
/ 19 июня 2020

Я кодировал вызов OkHttpRequest, чтобы заменить неисправный вызов Retrofit, и пришел к в этой строке :

Android запрещает сетевые вызовы в основном потоке, вы можете выполняйте синхронные вызовы только в том случае, если вы делаете это в отдельном потоке или в фоновой службе. Что затрудняло отслеживание этой проблемы, так это полное отсутствие журналов ошибок. Где мне искать подсказки, полезные для отладки моего кода?

В конце концов я изменил свой код с:

fun onScanFinished(barcode: Long) {
    uiScope.launch {
        BeerApi.retrofitService.searchByBarcode(barcode).enqueue(object : Callback<BeerES> {
            override fun onFailure(call: Call<BeerES>, t: Throwable) {
                Toast.makeText(getApplication(), "Failure: " + t.message, Toast.LENGTH_LONG)
                    .show()
            }
            override fun onResponse(call: Call<BeerES>, response: Response<BeerES>) {
                var beerScanned = response.body()
                if (beerScanned != null) {
                    UserApi.retrofitService.addScanned(
                        FirebaseAuth.getInstance().currentUser!!.uid,
                        beerScanned.beerId,
                        beerScanned.beerInfo.beerName
                    )
                }
            }
        })
    }
}

... на этот другой метод со своим собственным uiScope):

fun onScanFinished(barcode: Long) {
    uiScope.launch {
        BeerApi.retrofitService.searchByBarcode(barcode).enqueue(object : Callback<BeerES> {
            override fun onFailure(call: Call<BeerES>, t: Throwable) {
                Toast.makeText(getApplication(), "Failure: " + t.message, Toast.LENGTH_LONG)
                    .show()
            }
            override fun onResponse(call: Call<BeerES>, response: Response<BeerES>) {
                var beerScanned = response.body()
                if (beerScanned != null) {
                    addScanned(beerScanned)
                }
            }
        })
    }
}

private fun addScanned(beerScanned: BeerES) {
    uiScope.launch {
        UserApi.retrofitService.addScanned(
            FirebaseAuth.getInstance().currentUser!!.uid,
            beerScanned.beerId,
            beerScanned.beerInfo.beerName
        ).enqueue(object :  Callback<String> {
            override fun onFailure(call: Call<String>, t: Throwable) {
                 Toast.makeText(getApplication(), "Failure: " + t.message, Toast.LENGTH_LONG)
                    .show()
            }
            override fun onResponse(call: Call<String>, response: Response<String>) {
            }
        })
    }
}

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

...