2017-08-15 63 views
1

我試圖從這個URL分析JSON,https://fantasy.premierleague.com/drf/elements,但我從okhttp和郵差得到的響應是不同的。我也使用過在線API測試人員,並且在那裏還獲得了完整的JSON響應。我不知道爲什麼我的代碼無法正常工作。Okhttp3請求返回空響應以及不同郵件頭比郵差

任何人都可以幫我解決這個問題嗎?

下面是我用於快速測試的代碼。

val request = Request.Builder() 
      .url("https://fantasy.premierleague.com/drf/elements") 
      .get() 
      .addHeader("accept", "*/*") 
      .addHeader("accept-encoding", "gzip, deflate") 
      .addHeader("cache-control", "no-cache") 
      .addHeader("connection", "keep-alive") 
      .cacheControl(CacheControl.FORCE_NETWORK) 
      .build() 

    val httpClient = OkHttpClient() 
    httpClient.newCall(request).enqueue(object : okhttp3.Callback { 
     override fun onFailure(call: okhttp3.Call?, e: IOException?) { 
      Timber.d("FPL response failed = " + e?.message.toString()) 
     } 

     override fun onResponse(call: okhttp3.Call?, response: okhttp3.Response?) { 
      if (response!!.isSuccessful) { 

       val responseBody = response.body()?.string() 
       try { 
        val obj = JSONObject(responseBody) 
        Timber.d("FPL response = " + obj.toString()) 
       } catch (t: Throwable) { 
        Timber.e("Could not parse malformed JSON: " + t.message) 
       } 

       Timber.d("FPL response = $response") 
       Timber.d("FPL headers = " + response.headers()) 
       Timber.d("FPL body = " + responseBody) 
      } else { 
       Timber.d("FPL response failed = " + response.body().toString()) 
      } 
     } 
    }) 

我試圖複製郵差的代碼片段標題分別是:

Request request = new Request.Builder() 
    .url("https://fantasy.premierleague.com/drf/elements") 
    .get() 
    .addHeader("cache-control", "no-cache") 
    .addHeader("postman-token", "05ae03ef-cf44-618c-a82c-5762e245b771") 
    .build(); 

但遺憾的是沒有運氣無論是。

登錄:

D/HomeController$onAttach:L135: FPL response = Response{protocol=http/1.1, code=200, message=OK, url=https://fantasy.premierleague.com/drf/elements} 

D/HomeController$onAttach:L138: FPL headers = 
Server: Varnish 
Retry-After: 0 
Content-Type: application/json 
Content-Length: 0 
Accept-Ranges: bytes 
Date: Tue, 15 Aug 2017 22:17:18 GMT 
Via: 1.1 varnish 
Connection: close 
X-Served-By: cache-jfk8123-JFK 
X-Cache: MISS 
X-Cache-Hits: 0 
X-Timer: S1502835438.419014,VS0,VE0 

D/HomeController$onAttach:L139: FPL body = 

正如你所看到的,身體是空的, 「連接」 接近。

這是Postman得到的響應標題,有很大不同。

Accept-Ranges →bytes 
Age →14 
Allow →GET, HEAD, OPTIONS 
Cache-Control →no-cache, no-store, must-revalidate, max-age=0 
Connection →keep-alive 
Content-Encoding →gzip 
Content-Language →plfplen 
Content-Length →39518 
Content-Type →application/json 
Date →Tue, 15 Aug 2017 00:54:32 GMT 
Edge-Control →max-age=60 
Fastly-Debug-Digest →fdb44d2dd7c0b26c639a8b3476f8c63661c68707cc3b9446f8ed3941cd3fe01e 
Server →nginx 
Vary →Accept-Encoding 
Via →1.1 varnish 
Via →1.1 varnish 
X-Cache →HIT, MISS 
X-Cache-Hits →1, 0 
X-Frame-Options →DENY 
X-Served-By →cache-lcy1146-LCY, cache-jfk8143-JFK 
X-Timer →S1502758472.116470,VS0,VE82 

正如你所看到的,「連接」表示保持活躍。

有沒有我在我的Request.Builder()中失蹤以獲得此工作?

編輯:

所以,我決定嘗試製作使用AsyncTask的要求,並得到了充分的JSON回來,你可以在日誌中看到的。我不明白爲什麼Okhttp3不起作用。

  val url = params[0] 
      var stream: InputStream? = null 
      var connection: HttpsURLConnection? = null 
      var result: String? = null 
      try { 
       connection = url?.openConnection() as HttpsURLConnection? 
       // Timeout for reading InputStream arbitrarily set to 3000ms. 
       connection?.readTimeout = 3000 
       // Timeout for connection.connect() arbitrarily set to 3000ms. 
       connection?.connectTimeout = 3000 
       // For this use case, set HTTP method to GET. 
       connection?.requestMethod = "GET" 
       // Already true by default but setting just in case; needs to be true since this request 
       // is carrying an input (response) body. 
       connection?.doInput = true 
       // Open communications link (network traffic occurs here). 
       connection?.connect() 

       val responseCode = connection?.responseCode 

       if (responseCode != HttpsURLConnection.HTTP_OK) { 
        throw IOException("HTTP error code: " + responseCode) 
       } 
       // Retrieve the response body as an InputStream. 
       stream = connection?.inputStream 

       Timber.d("httpurl stream = " + connection?.inputStream.toString()) 

       if (stream != null) { 
        // Converts Stream to String with max length of 500. 
       result = readStream(stream, 500) 
       } 
      } finally { 
       // Close Stream and disconnect HTTPS connection. 
       if (stream != null) { 
        stream.close() 
       } 
       if (connection != null) { 
        connection.disconnect() 
       } 
      } 

      return result 

登錄:

D/HomeController$NetworkA:L266: httpurl response = [{"id":1,"photo":"48844.jpg","web_name":"Ospina","team_code":3,"status":"a","code":48844,"first_name":"David","second_name":"Ospina","squad_number":13,"news":"","now_cost":50, .... }] 
+0

該URL有301嘗試在末尾添加斜線重定向('的https:// fantasy.premierleague.com/DRF /元/')去重定向的URL 。 OkHttp應該會自動遵循重定向,所以這可能沒有幫助。但是,使用'curl'(不遵循重定向)進行測試,我會得到與使用原始URL的OkHttp相同的結果,如果在末尾添加'/',我會得到JSON響應。 – CommonsWare

+0

@CommonsWare好吧,只是嘗試添加'/'到最後,但仍然沒有運氣。我也用'curl'試過了URL,它確實返回了響應。我不知道爲什麼這不使用Okhttp3。 – MikeOscarEcho

+0

我能想到的唯一的另一件事是,也許OkHttp不標準化HTTP頭大寫,並且服務器可能不喜歡你的全小寫頭名稱。 – CommonsWare

回答

1

您的問題是User-Agent頭。這是一個工作示例:

fun syncGetOkHttp() { 
    println("\n===") 
    println("OkHttp") 
    println("===") 
    val client = OkHttpClient().newBuilder() 
      .addNetworkInterceptor { chain -> 
       val (request, response) = chain.request().let { 
        Pair(it, chain.proceed(it)) 
       } 

       println("--> ${RequestLine.get(request, Proxy.Type.HTTP)})") 
       println("Headers: (${request.headers().size()})") 
       request.headers().toMultimap().forEach { k, v -> println("$k : $v") } 

       println("<-- ${response.code()} (${request.url()})") 

       val body = if (response.body() != null) 
        GZIPInputStream(response.body()!!.byteStream()).use { 
         it.readBytes(50000) 
        } else null 

       println("Response: ${StatusLine.get(response)}") 
       println("Length: (${body?.size ?: 0})") 

       println("""Body: ${if (body != null && body.isNotEmpty()) String(body) else "(empty)"}""") 
       println("Headers: (${response.headers().size()})") 
       response.headers().toMultimap().forEach { k, v -> println("$k : $v") } 

       response 
      } 
      .build() 

    Request.Builder() 
      .url(url) 
      .header("Accept", "application/json") 
      .header("User-Agent", "Mozilla/5.0") 
      .build() 
      .let { client.newCall(it).execute() } 
} 
+0

是的,就是這樣!你碰巧知道爲什麼這些是必需的?不介意多學習一點。謝謝您的幫助。 – MikeOscarEcho

+1

@MikeOscarEcho直到服務器;也許它想要設置一個cookie。 –