Android Retrofit2 reddit 404 未找到

Android Retrofit2 reddit 404 Not Found

我正在使用改装为 Reddit 创建 Android 客户端。 在 logcat 获取令牌工作正常,但是当我尝试获取登录用户的信息时,我收到“404 Not Found”。 这是我的 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)

这是我的代码:

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


}

我正在按照 here 中的说明进行操作。 我的改造版本是:

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'

最后一条日志:

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)

可能的原因之一可能是您的 BASE URL。

根据 Retrofit 2,base url 不得以“/”结尾。

请从基数 URL 中删除“/”并尝试一个。

在 Retrofit 1.9 中,它工作正常。

干杯!

由于 Retrofit 2.0 如何使用 Http Resolve 来解析端点的 uri 方案,如果您像这样指定 baseurl http://hello.com 并将端点 URL 指定为 /world/foo,它将休息。

您需要使用基 URL http://hello.com/ 和端点 URL world/foo。

/ 与众不同。

如果对您有帮助,请告诉我,否则我会给您其他解决方案。 你的问题和我认为的这个问题一样:

你可以检查这个问题:Link

@POST("api/v1/me")

删除第一个字符处的“/”url,因为改造 2.0 需要 BASEURL 必须以“/”结尾。我在您的代码中找不到其他问题。你应该检查你的 Header 是否有任何空值或检查 API link

您对端点 /api/v1/me 的 API 调用是 POST 方法

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

根据他们的 documentation for enpoint /api/v1/me 你应该使用 GET 请求。

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

我没有测试该解决方案,但它似乎是 404 的原因,as in another post 它解决了问题(python)。

我终于找到了解决办法!我打电话时用错了 grant_type!我改了,现在可以用了!