Android Retrofit2 reddit 404 未找到
Posted
技术标签:
【中文标题】Android Retrofit2 reddit 404 未找到【英文标题】:Android Retrofit2 reddit 404 Not Found 【发布时间】:2017-02-24 17:38:53 【问题描述】:我正在使用改造为 Reddit 创建一个 android 客户端。 在 logcat 获取令牌工作正常,但是当我尝试获取登录用户的信息时,我得到“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)
这是我的代码:
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)
【问题讨论】:
【参考方案1】:其中一个可能的原因可能是您的 BASE URL。
根据 Retrofit 2,base url 不能以 '/' 结尾。
请从基本 URL 中删除“/”并尝试一个。
在 Retrofit 1.9 中,它运行良好。
干杯!!!
【讨论】:
请使用库 compile 'com.squareup.okhttp3:logging-interceptor:3.4.1' 分享您的请求日志 它会给请求和响应加上Header信息。要使用这个库调用 :: HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); // 设置你想要的日志级别 logging.setLevel(HttpLoggingInterceptor.Level.BODY); okHttpClientBuilder.interceptors().add(logging); 我已经编辑了我的帖子并添加了新的日志输出。 您的网址错误“https://oauth.reddit.com/api/v1/me”。它必须是 "https://www.reddit.com/api/v1/me" 。 ***注意在 https:// 之后添加空格。您需要删除它。 如果我将 url 更改为“reddit.com/api/v1/me”,我会收到“403 Forbidden”。【参考方案2】:由于 Retrofit 2.0 如何使用 Http Resolve 来解析端点的 uri 方案,如果您将 baseurl 指定为 http://hello.com
并将端点 URL 指定为 /world/foo,它将中断。
您需要使用基本 URL http://hello.com/
和端点 URL world/foo。
/ 有所作为。
如果对你有帮助,请通知我,否则我会给你另一个解决方案。 您的问题与我认为的这个问题相同:Link
你可以检查这个问题:Link
【讨论】:
感谢您的回答@jamil-hasnine-tamim,但我已经尝试过了! 不,它没有。现在我收到“错误 403,禁止访问”。 遇到了同样的问题,但在我这边,我切换帐户后它才开始工作。顺便说一句,当基本 URL 不是以/
.. 结尾时,Retrofit2 崩溃了,这很明显:)
@milosmns 是的,你是对的 Retrofit2 由于/
而崩溃【参考方案3】:
@POST("api/v1/me")
删除第一个字符 url 处的“/”,因为改造 2.0 需要 BASEURL 必须以“/”结尾。我在您的代码中找不到其他问题。如果有任何空值,您应该检查您的 Header 或检查 API 链接
【讨论】:
【参考方案4】:您对端点 /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)。
【讨论】:
【参考方案5】:我终于找到了我的解决方案!我用错误的 grant_type 拨打电话!我改变了它,现在它可以工作了!
【讨论】:
以上是关于Android Retrofit2 reddit 404 未找到的主要内容,如果未能解决你的问题,请参考以下文章
Retrofit2.0 android.os.NetworkOnMainThreadException解决方法
Android Studio - 使用 retrofit2 从 restdb 获取信息
Android Retrofit2中Part和PartMap的区别
Android 网络框架 Retrofit2.0介绍使用和封装