ABOUT ME

Today
Yesterday
Total
  • Retrofit을 사용한 PUT 요청은 통과하지 않지만 curl은 통과합니다.
    카테고리 없음 2020. 8. 9. 02:27

    질문

    Retrofit을 사용하는 Android 앱에서 MongoDB 문서를 업데이트해야하는 Flask API로 PUT 요청을 보내고 싶습니다. 전체 URL로 curl 명령을 실행하면 잘 작동하지만 개조 기능을 실행할 때 아무 일도 일어나지 않습니다.

    서버의 로그를 보면 모든 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
    

    Mongo는 이상한 것을 기록하지 않습니다. Retrofit의 또 다른 PUT 요청은 매력처럼 작동합니다.

    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

    오작동하는 Retrofit 호출을 대체하기 위해 OkHttp 요청 호출을 코딩하는 중 이 줄 :

    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를 가진 다른 메서드에서 두 번째 Api 호출을 추출) :

    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>) {
                }
            })
        }
    }

    이것이 도움이되기를 바랍니다.



     

     

     

     

    출처 : https://stackoverflow.com/questions/62457901/put-request-with-retrofit-doesnt-get-through-but-curl-does

    댓글

Designed by Tistory.