Android Retrofit2 reddit 404 Not Found
Asked Answered
U

5

6

I am using retrofit to create an Android Client for the Reddit. At logcat to get the toke is work fine, but when I am trying to get the information of the login user, I am getting "404 Not Found". Here is my logcat:

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)

Here is my code:

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;
    }


}

I am following the instructions from this here. My retrofit version is:

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'

Last 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)
Untangle answered 15/10, 2016 at 9:53 Comment(0)
U
0

I finally find my solution! I was making the call with wrong grant_type! I change it, and now it is working!

Untangle answered 25/10, 2016 at 7:3 Comment(0)
L
1

One of the possible cause may be your BASE URL.

According to Retrofit 2, base url must not end with '/'.

Please remove '/' from base URL and try one.

In Retrofit 1.9, it was working fine.

Cheers!!!

Labiche answered 15/10, 2016 at 9:58 Comment(8)
Please share logs of your request using library compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'Labiche
It will give the request and response with Header information. To use this library call :: HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // set your desired log level logging.setLevel(HttpLoggingInterceptor.Level.BODY); okHttpClientBuilder.interceptors().add(logging);Labiche
I have edit my post and add the new output of the log.Untangle
Your URL is wrong "https:// oauth.reddit.com/api/v1/me". It must be "https:// www.reddit.com/api/v1/me" . ***Note Space added after https://. You need to remove this.Labiche
if I change the url to "reddit.com/api/v1/me", I getting "403 Forbidden".Untangle
403 Forbidden means you don't have access (Access Denied). Now, to connect to reddit, you need to first hit the OAuth Request, which will return you an Authrization Token, Using that token you need to get logged in user's profile. This authorization token must go as Header of /api/v1/me request.Labiche
But I already have the Authorization at my Header! You can see it at the log, I have already provide!Untangle
Your Authorization header must be like this: Authorization: "bearer tokenToken" or Authorization: 'bearer tokenToken'Labiche
C
1

Your API call for endpoint /api/v1/me is POST method

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

According to their documentation for enpoint /api/v1/me you should use GET requests.

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

I didn't test that solution but it seems to be the cause for 404, as in another post it solved the problem (for python).

Carisacarissa answered 23/10, 2016 at 17:21 Comment(0)
O
0

Due to how Retrofit 2.0 uses Http Resolve for resolving the uri scheme of your endpoints, if you specify the baseurl like this http://hello.com and the endpoint URL as /world/foo it will break.

You need to use base URL http://hello.com/ and endpoint URL world/foo.

The / makes the difference.

if it helps you please inform me or i will give you another solution. Your problem is same as this problem i think: Link

And you can check this issues : Link

Oswin answered 17/10, 2016 at 10:6 Comment(4)
Thanks for your answer @jamil-hasnine-tamim, but I have already try this!Untangle
No, it didn't. Now I am getting "Error 403, Forbidden".Untangle
Had the same problem, but on my side it just started working after I switched the account. Btw, Retrofit2 crashed when the base URL was not ending with a /.. so that was kinda obvious :)Quarterage
@Quarterage yup you are right Retrofit2 Crashed due to /Oswin
S
0

@POST("api/v1/me")

remove "/" at first character url because retrofit 2.0 need BASEURL must end with "/".. I can't find others problem in your code. You should check your Header if there is any null value or check back the API link

Somerset answered 18/10, 2016 at 14:28 Comment(0)
U
0

I finally find my solution! I was making the call with wrong grant_type! I change it, and now it is working!

Untangle answered 25/10, 2016 at 7:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.