2016-10-15 21 views
6

Używam retrofitu, aby utworzyć klienta Androida dla Reddit. Na logcat, aby uzyskać toke działa dobrze, ale gdy próbuję uzyskać informacje o użytkowniku logowania, otrzymuję komunikat "404 Not Found". Oto moja logcat:Android Retrofit2 reddit 404 Not Found

D/OkHttp: --> POST https://oauth.reddit.com/api/v1/me http/1.1 
D/OkHttp: Content-Length: 0 
D/OkHttp: Authorization: bearer myToken 
D/OkHttp: User-Agent: MyRedditClient/0.1 by myusername 
D/OkHttp: --> END POST 
D/OkHttp: <-- 404 Not Found https://oauth.reddit.com/api/v1/me (677ms) 

Oto mój kod:

import java.io.IOException; 

import okhttp3.Interceptor; 
import okhttp3.OkHttpClient; 
import okhttp3.Request; 
import okhttp3.Response; 
import okhttp3.logging.HttpLoggingInterceptor; 
import retrofit2.Retrofit; 
import retrofit2.converter.gson.GsonConverterFactory; 

public class ServiceAuthGenerator { 

    public static final String API_BASE_URL = "https://www.reddit.com/"; 

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 

    private static Retrofit.Builder builder = 
      new Retrofit.Builder() 
        .baseUrl(API_BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create()); 

    public static <S> S getTokenService(Class<S> serviceClass) { 
     return getTokenService(serviceClass, null, null); 
    } 

    public static <S> S getTokenService(Class<S> serviceClass, String username, String password) { 
     if (username != null && password != null) { 
      String credentials = username + ":" + password; 
      final String basic = 
        "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); 

      httpClient.addInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Interceptor.Chain chain) throws IOException { 
        Request original = chain.request(); 

        Request.Builder requestBuilder = original.newBuilder() 
          .header("Authorization", basic) 
          .header("Accept", "application/json") 
          .method(original.method(), original.body()); 

        Request request = requestBuilder.build(); 
        return chain.proceed(request); 
       } 
      }); 
     } 

     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 

     OkHttpClient client = httpClient.addInterceptor(interceptor).build(); 
     Retrofit retrofit = builder.client(client).build(); 
     return retrofit.create(serviceClass); 
    } 

} 

import java.io.IOException; 

import okhttp3.Interceptor; 
import okhttp3.OkHttpClient; 
import okhttp3.Request; 
import okhttp3.Response; 
import okhttp3.logging.HttpLoggingInterceptor; 
import retrofit2.Retrofit; 
import retrofit2.converter.gson.GsonConverterFactory; 

public class ServiceInfoGenerator { 

    public static final String API_BASE_URL = "https://oauth.reddit.com/"; 

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 

    private static Retrofit.Builder builder = 
      new Retrofit.Builder() 
        .baseUrl(API_BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create()); 

    public static <S> S retrieveInfoService(Class<S> serviceClass) { 
     return retrieveInfoService(serviceClass, null, null); 
    } 

    public static <S> S retrieveInfoService(Class<S> serviceClass, final String authToken, final String username) { 
     if (authToken != null && username != null) { 
      httpClient.addInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Chain chain) throws IOException { 
        Request original = chain.request(); 

        // Request customization: add request headers 
        Request.Builder requestBuilder = original.newBuilder() 
          .header("Authorization", " bearer "+authToken) 
          .header("User-Agent", "MyRedditClient/0.1 by "+username) 
          .method(original.method(), original.body()); 

        Request request = requestBuilder.build(); 
        return chain.proceed(request); 
       } 
      }); 
     } 

     HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
     interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); 

     OkHttpClient client = httpClient.addInterceptor(interceptor).build(); 
     try { 
      client.interceptors().add(new UserAgentInterceptor(username)); 
     } catch (Exception e){ 
      Log.i("ServiceInfoGenerator", "retrieveInfoService: "+e.getMessage()); 
     } 
     Retrofit retrofit = builder.client(client).build(); 
     return retrofit.create(serviceClass); 
    } 
} 

import java.util.Map; 

import retrofit2.Call; 
import retrofit2.http.Field; 
import retrofit2.http.FormUrlEncoded; 
import retrofit2.http.GET; 
import retrofit2.http.Headers; 
import retrofit2.http.POST; 
import retrofit2.http.QueryMap; 

public interface MyApiRetrofit { 

    @POST("/api/v1/access_token") 
    @FormUrlEncoded 
    Call<Authorize> accessToken(@Field(("grant_type")) String grantType, @Field(("username")) String username, @Field(("password")) String password); 

    @POST("/api/v1/me") 
    Call<Authorize> retrieveMyInfo(); 

} 

import android.os.AsyncTask; 
import android.util.Log; 

import com.havistudio.myreddit.api.Authorize; 
import com.havistudio.myreddit.api.MyApiRetrofit; 

import java.io.IOException; 

import retrofit2.Call; 
import retrofit2.Callback; 
import retrofit2.Response; 

public class TestAPITask2 extends AsyncTask<Void, Void, Void> { 

    private static final String TAG = "TestAPITask2"; 
    private String myAccessToken; 
    private String myRefreshToken; 

    @Override 
    protected Void doInBackground(Void... voids) { 

     MyApiRetrofit loginService = ServiceAuthGenerator.getTokenService(MyApiRetrofit.class, "client_id", "client_secret"); 
     Call<Authorize> call = loginService.accessToken("password", "myusername", "mypassword"); 
     call.enqueue(new Callback<Authorize>() { 
      @Override 
      public void onResponse(Call<Authorize> call, Response<Authorize> response) { 
       if (response.isSuccessful()) { 
        // user object available 
        Log.i(TAG, "isSuccessful"); 
        Authorize temp = response.body(); 
        myAccessToken = temp.getAccessToken(); 
        Log.i(TAG, temp.toString()); 

        MyApiRetrofit myInfoService = ServiceInfoGenerator.retrieveInfoService(MyApiRetrofit.class, myAccessToken, "myusername"); 
        Call<Authorize> call2 = myInfoService.retrieveMyInfo(); 
        try { 
         Authorize user = call2.execute().body(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 

       } else { 
        // error response, no access to resource? 
        Log.i(TAG, "error response"); 
       } 
      } 

      @Override 
      public void onFailure(Call<Authorize> call, Throwable t) { 
       // something went completely south (like no internet connection) 
       Log.d(TAG, t.getMessage()); 
      } 
     }); 


     return null; 
    } 


} 

ja postępując zgodnie z instrukcjami z tego here. Moja wersja modernizacyjny jest:

compile 'com.squareup.retrofit2:retrofit:2.0.2' 
compile 'com.squareup.retrofit2:converter-gson:2.0.2' 
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0' 

Ostatni log:

10-15 13:17:41.434 9968-9968 D/OkHttp: --> POST https://oauth.reddit.com/api/v1/me http/1.1 
10-15 13:17:41.434 9968-9968 D/OkHttp: Content-Length: 0 
10-15 13:17:41.434 9968-9968 D/OkHttp: Authorization: bearer tokenToken 
10-15 13:17:41.434 9968-9968 D/OkHttp: User-Agent: MyRedditClient/0.1 by myusername 
10-15 13:17:41.434 9968-9968 D/OkHttp: --> END POST (0-byte body) 
10-15 13:17:41.988 9968-9968 D/OkHttp: <-- 404 Not Found https://oauth.reddit.com/api/v1/me (553ms) 
10-15 13:17:41.988 9968-9968 D/OkHttp: Content-Type: application/json; charset=UTF-8 
10-15 13:17:41.988 9968-9968 D/OkHttp: x-frame-options: SAMEORIGIN 
10-15 13:17:41.988 9968-9968 D/OkHttp: x-content-type-options: nosniff 
10-15 13:17:41.988 9968-9968 D/OkHttp: x-xss-protection: 1; mode=block 
10-15 13:17:41.989 9968-9968 D/OkHttp: expires: -1 
10-15 13:17:41.989 9968-9968 D/OkHttp: cache-control: private, s-maxage=0, max-age=0, must-revalidate, max-age=0, must-revalidate 
10-15 13:17:41.990 9968-9968 D/OkHttp: x-ratelimit-remaining: 598.0 
10-15 13:17:41.990 9968-9968 D/OkHttp: x-ratelimit-used: 2 
10-15 13:17:41.990 9968-9968 D/OkHttp: x-ratelimit-reset: 136 
10-15 13:17:41.990 9968-9968 D/OkHttp: set-cookie: loid=Fsx2GnGYmufCQZ6cfT; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Mon, 15-Oct-2018 10:17:44 GMT; secure 
10-15 13:17:41.991 9968-9968 D/OkHttp: set-cookie: loidcreated=2016-10-15T10%3A17%3A44.173Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Mon, 15-Oct-2018 10:17:44 GMT; secure 
10-15 13:17:41.991 9968-9968 D/OkHttp: x-ua-compatible: IE=edge 
10-15 13:17:41.991 9968-9968 D/OkHttp: set-cookie: loid=Q52c9gouzuGGdg7UXW; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Mon, 15-Oct-2018 10:17:44 GMT; secure 
10-15 13:17:41.991 9968-9968 D/OkHttp: set-cookie: loidcreated=2016-10-15T10%3A17%3A44.189Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Mon, 15-Oct-2018 10:17:44 GMT; secure 
10-15 13:17:41.991 9968-9968 D/OkHttp: X-Moose: majestic 
10-15 13:17:41.991 9968-9968 D/OkHttp: Content-Length: 38 
10-15 13:17:41.992 9968-9968 D/OkHttp: Accept-Ranges: bytes 
10-15 13:17:41.992 9968-9968 D/OkHttp: Date: Sat, 15 Oct 2016 10:17:44 GMT 
10-15 13:17:41.992 9968-9968 D/OkHttp: Via: 1.1 varnish 
10-15 13:17:41.992 9968-9968 D/OkHttp: Connection: keep-alive 
10-15 13:17:41.992 9968-9968 D/OkHttp: X-Served-By: cache-ams4426-AMS 
10-15 13:17:41.992 9968-9968 D/OkHttp: X-Cache: MISS 
10-15 13:17:41.992 9968-9968 D/OkHttp: X-Cache-Hits: 0 
10-15 13:17:41.992 9968-9968 D/OkHttp: X-Timer: S1476526664.126987,VS0,VE109 
10-15 13:17:41.993 9968-9968 D/OkHttp: Server: snooserv 
10-15 13:17:42.002 9968-9968 D/OkHttp: {"message": "Not Found", "error": 404} 
10-15 13:17:42.002 9968-9968 D/OkHttp: <-- END HTTP (38-byte body) 

Odpowiedz

0

W końcu znajdę moje rozwiązanie! Dzwoniłem z błędem grant_type! Zmieniam to, a teraz działa!

0

Jedną z możliwych przyczyn może być bazę domową.

Zgodnie z Retrofit 2 adres bazowy nie może kończyć się znakiem "/".

Usuń "/" z podstawowego adresu URL i spróbuj go.

W Retrofit 1.9 wszystko działało poprawnie.

Pozdrawiam !!!

+0

Usunąłem błąd "Nie znaleziono 404" i wciąż otrzymuję komunikat "404 nie znaleziono". – KostasC

+0

Proszę udostępnić logi swoich żądań za pomocą biblioteki compile 'com.squareup.okhttp3: logging-interceptor: 3.4.1' –

+0

To da zapytanie i odpowiedź z informacjami nagłówka. Aby użyć tego wywołania biblioteki :: HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // ustaw żądany poziom rejestru logging.setLevel (HttpLoggingInterceptor.Level.BODY); okHttpClientBuilder.interceptors(). Add (logowanie); –

0

Z tego powodu, jak Retrofit 2.0 używa Http Resolve do rozwiązania schematu Uri punktów końcowych, jeśli podasz baseurl taki jak ten http://hello.com, a adres URL punktu końcowego jako/world/foo zostanie przerwany.

Należy użyć podstawowego adresu URL http://hello.com/ i adresu URL punktu końcowego world/foo.

The/robi różnicę.

jeśli to pomoże, proszę poinformuj mnie lub dam ci inne rozwiązanie. Twój problem jest taki sam, jak ten problem myślę: Link

I można to sprawdzić kwestie: Link

+0

Dzięki za odpowiedź @ jamil-hasnine-tamim, ale już spróbowałem! – KostasC

+0

Nie działa? @KosrasC –

+0

Nie, nie udało się. Teraz otrzymuję komunikat "Błąd 403, Zabroniony". – KostasC

0

@POST("api/v1/me")

usunięcie "/" na pierwszy znak url ponieważ modernizacja 2,0 potrzebują baseURL musi kończyć się "/".. Nie mogę znaleźć innych problemów w twoim kodzie. należy sprawdzić nagłówek, jeśli istnieje jakakolwiek wartość null lub sprawdź powrotem link api

1

Twój wywołanie API dla punktu końcowego /api/v1/me jest POST metoda

@POST("/api/v1/me") 
Call<Authorize> retrieveMyInfo(); 

Według ich documentation dla enpoint /api/v1/me należy użyć GET żądań.

@GET("/api/v1/me") 
Call<Authorize> retrieveMyInfo(); 

nie testowanie tego rozwiązania, ale wydaje się być przyczyną 404 as in another post to rozwiązano problemu (pytona).