Retrofit动态传递Header和Body遇401错误,请求技术支持
Let's break down the possible causes of your 401 error and fix them step by step:
1. Critical Issue: Retrofit Singleton Reuses Old Token
Looking at your ApiClient class, the retrofit instance is a static variable. Once it's created the first time, subsequent calls to getApiClient() will ignore the new token and reuse the original OkHttpClient with the initial token. This is a common pitfall when using static singletons with dynamic authentication tokens.
Fix:
Modify your ApiClient to either avoid reusing the static Retrofit instance (for token-changing scenarios) or implement a way to update the token without recreating Retrofit entirely. Here's a quick fix for immediate testing:
public class ApiClient { // Remove static Retrofit instance to ensure we create a new client per token public static Retrofit getApiClient(final String token) { OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); httpClient.addInterceptor(new Interceptor() { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request original = chain.request(); Request request = original.newBuilder() .header("Authorization", "Bearer " + token) .method(original.method(), original.body()) .build(); return chain.proceed(request); } }); // Add logging interceptor to debug request headers (optional but helpful) HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); httpClient.addInterceptor(logging); return new Retrofit.Builder() .baseUrl(BaseUrl.BASE_URL) .client(httpClient.build()) .addConverterFactory(GsonConverterFactory.create()) .build(); } }
2. Verify Token Validity & Format
A 401 error almost always points to authentication failure. Check these:
- Is the
accessTokenyou're passing valid? Test it directly in Postman/curl with the same endpoint and header:
If Postman also returns 401, your token is likely expired, invalid, or lacks permissions for theAuthorization: Bearer YOUR_ACCESS_TOKEN/api/userData/registerNewUserDataendpoint. - Ensure there's a space between
Bearerand the token (your code does this correctly, but double-check if the token itself has leading/trailing spaces). - Confirm the server expects the header key to be
Authorization(some APIs useAuth-Tokenor other keys).
3. Fix Response Handling to Avoid Crashes
Your current onResponse code will crash when response.code() == 401 because response.body() will be null. Update it to handle error states properly:
@Override public void onResponse(Call<RegisterModel> call, Response<RegisterModel> response) { Log.e("code", response.code() + ""); if (response.isSuccessful()) { RegisterModel model = response.body(); if (model != null && "success".equals(model.getMessage())) { Toast.makeText(RegisterClass.this, "Data Sent Successfully", Toast.LENGTH_SHORT).show(); finish(); startActivity(getIntent()); } } else { if (response.code() == 401) { Toast.makeText(RegisterClass.this, "Authentication failed: Invalid or expired token", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(RegisterClass.this, "Request failed with code: " + response.code(), Toast.LENGTH_SHORT).show(); } } }
4. Check if Request Body Meets Server Requirements
While 401 is auth-related, some servers might reject requests with malformed bodies even before checking auth. Use the logging interceptor we added to verify your request body matches what the server expects.
Start with fixing the Retrofit singleton issue first—it's the most likely culprit here. Then use the logging interceptor to confirm your Authorization header is being sent correctly.
内容的提问来源于stack exchange,提问作者Sudeep

