问题
My api base url is:
https://locodealapi.herokuapp.com/api/deals
In postman pass following in header and it works fine.
x-access-token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX25hbWUiOiJkZWFsQWRtaW4iLCJ1c2VyX3Bhc3N3b3JkIjoiY2U5MDZkNDkzMWY3NmFhZWFmZTViNjM0YTg3Y2RkYzQ4YjMzNmUzYmVlZDU1N2ZhZTI0YzMxZTY3YmQyN2NhZDg4NDJmNzJlNTJlNGUyODc5ZWVkODY1MDljYzY5ODJlNDYwMjU0Mzk4ODQzMTljMTQxMGMwOTcxNGU0Y2MxMDNiMDQwYjkwOTQ1OTMyMjYwMGI1MjgwMmRkOTc2YTE4OGE5MTZiMWU4ZmU1YmY1ZWZiNTlkYjc2NDhmMjQxOTg0ODdiMWE5OGVhMjg2ZWZjZDI1M2Y5ZWUxNTQ0OTI3ODZiYjY3NzNmZTZjNGY3ODhmNzJjMzQ0NTEwMzg2NjkyNzIzMjNiMjZmYjFhMmUzYjE0ZTQ0Nzc0NzljMTExMzNkZjIwMmE3ODY2OGIxZjdiY2NlZjQ5NTM0YTJhYzk5N2Y0MTc0NzU2OTkwOTg5NjQ1YzljNWQxYTZkYmUyZTI1ZjFlNDE3YjdhYWI1N2QyZGJhNmVmOWEwNzk5N2Q5ZDcyNTgxMzUyYzc4Y2IxY2RiMDRmNDFkZjMwNzdjYzAxMGM2YmYzYWMzOTQ5OTJjN2Y3ZGVmYmE3YzllZWMxMzI5ODhlODBiM2RmYWE5NTVhMzE3NTgxNThiZjYxYjYyN2U4Y2UzOTg2NmRkODk2YzBlZDkzNDJlMzhiMzhkM2Q0ZTY0YWIzZWIwNGU4YmU5MGQwNmM2NTg2OWYyNzZkMzgyOTU3MTFkODgyNjI4NGIxMjkzYzQ0ZGNjMWM3ZjU2YmE4OGM5MTkyNDMzZWY0YTcwZGE2NTkzMzAwZmUzMGMxYjkwOWY5YmJjMDhmY2M5Zjk3NjUwYmJkOTVhNzExNWVlOGY3MjI5N2Q4ZGY4MjZiMTk0MTBlZjQ0OWZkMTQ1NTg3Nzc2NjUxZDI5OGMyYzMwMTZiMDMxMGEwZjRlMWQ4NzgwZTExYmVkOTZhYzg3MDU2YzIwYWU4ODZiYjI3NGZkNGVhZGMzMjQ0ZjlmMmZkMGIyMGMzZTAyZjI1NGQ3OWYzYzhiM2FmZGJiM2UzYTM1YTA2MjNjMTQwY2JmNzMxZWMxYjE2Y2VmNmIwY2RhMjQ1YjkzZmY4NzQ1MGRjNWFhZDE2MzdkNTQ5ZjM5ZDkwZjk5MWFiNWMxNTcwNWExYWJjYWQxYzQyYjNmMTViN2Y5N2I0YTc1ZDA2YTgwYjkwOWI0ZDJlZjRiNWE0NzdhMTMzYWI0ODkwMmIyNWFiM2VmYTMzNDdjMDcxODQ4NmMwYmU2NGQxYzUxMjA1ZTMwYjU5NjY3Yjk5ZTVlYTdkZWNiMWE4MWRkNjcyYzEwMzU5YmM2NGNlZWI3ZTEyOWJlYjZjYWUzYTM0ZjM0M2NiYjk4NyIsImNyZWF0ZXRpbWUiOm51bGwsImZpcnN0X25hbWUiOm51bGwsImxhc3RfbmFtZSI6bnVsbCwiYWdlIjpudWxsLCJzZXgiOm51bGwsImRvYiI6bnVsbCwic3RhdHVzIjpudWxsLCJpdGVyYXRpb24iOjEwMDAwLCJ1c2VyX3R5cGUiOiIwIiwidXNlcl9pbWFnZSI6bnVsbCwic2FsdCI6Ikh1dm9VQ3FRak81Mi9BbkJIdmp2MldEMERod2JmM0R4ZXV6ZWJMSlFYK3hZTUptMmRJSUw3VFYvcnFVVXFVNUpmRlY0dHhkMHNCcXhLbnVNakU2YlNzVnpaQ0dWVXg3YmY4MGNubTR5WnB5OElEUWowY1crTXhCUXdvMFNja2UzT0FnVk4zd2pnNmlxSVk3VnJwRmw1WTNLRzFwY1NMelZjREJiME9XdXdjcz0iLCJpYXQiOjE1MTAxMjY1OTUsImV4cCI6MTUxODc2NjU5NX0.5XFJnJqTsfID9uqOwkNf46oraj9jDxic7qNSqBdunD0
In retrofit Interface I have following but get 400 Bad request
@POST("api/deals")
Call<ResponseBody> deals(@Header("x-access-token") String x_access_token)
Calling code:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://locodealapi.herokuapp.com")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
AppRestAPI client = retrofit.create(AppRestAPI.class);
Call<ResponseBody> call1 = client.deals(
token
);
call1.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.i(TAG, "The response is " + response.message());
Log.i(TAG, "The response is " + response.body());
try {
Log.i(TAG, "The response is " + response.errorBody().string());
if (response.code() == 400) {
Log.v("Error code 400",response.errorBody().string());
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "onFailure: Failed", t);
}
});
OKHTTP Log interceptor
11-21 21:14:30.939 3253-3342/? D/OkHttp: --> POST https://locodealapi.herokuapp.com/api/deals
11-21 21:14:30.939 3253-3342/? D/OkHttp: Content-Length: 0
11-21 21:14:30.940 3253-3342/? D/OkHttp: x-access-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoyNSwidXNlcl9uYW1lIj....
11-21 21:14:30.942 3253-3342/? D/OkHttp: --> END POST (0-byte body)
11-21 21:14:34.188 3253-3342/? D/OkHttp: <-- 400 Bad Request https://locodealapi.herokuapp.com/api/deals (3246ms)
11-21 21:14:34.189 3253-3342/? D/OkHttp: Connection: close
11-21 21:14:34.189 3253-3342/? D/OkHttp: Server: Cowboy
11-21 21:14:34.189 3253-3342/? D/OkHttp: Date: Tue, 21 Nov 2017 15:29:33 GMT
11-21 21:14:34.190 3253-3342/? D/OkHttp: Content-Length: 0
11-21 21:14:34.191 3253-3342/? D/OkHttp: <-- END HTTP (0-byte body)
11-21 21:14:34.196 3253-3253/? I/BaseDrawerActivity: The response is Bad Request
11-21 21:14:34.196 3253-3253/? I/BaseDrawerActivity: The response is null
11-21 21:14:34.196 3253-3253/? I/BaseDrawerActivity: The response is
Note: The same code works fine in local nodejs server (http only)
回答1:
1.Frist thing your api is a GET Method so use @GET instead @POST
Second try to change url base url in retrofit .baseUrl("https://locodealapi.herokuapp.com") to .baseUrl("https://locodealapi.herokuapp.com/") this will work. or leave your problem in comment 2.this is sample code
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder().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().
method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.addInterceptor(interceptor).connectTimeout(60,TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://locodealapi.herokuapp.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient).build();
UserApi userApi = retrofit.create(UserApi.class);
Call<ResponseBody> call = userApi.deals("your token");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,retrofit2.Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {}
});
}
@GET("api/deals") Call deals(@Header("x-access-token") String x_access_token);
回答2:
Greeting of the day!
Try this:
@FormUrlEncoded
@POST("/api/deals")
Call<ResponseBody> deals(@Header("x-access-token") String x_access_token, @Field("<parameter_name>") String parameter);
Call api as below:
Call<ResponseBody> call = client.deals(token,"<parameter>");
Here, i am assuming that the API has a parameter which can be passed as 2nd argument in the method deals(). You can pass multiple parameters as the arguments of the method.
Refer the following link for more details: https://futurestud.io/tutorials/retrofit-send-data-form-urlencoded
I hope, this solves your problem. If not, please provide complete details of the API that you want to call.
回答3:
A 400 response
means that it's a disagreement between your request and the server, but that the request was created, sent, and a response was parsed. Which means Retrofit
is working fine. You can use OkHttp's logging interceptor to log the raw request and compare it with what the server expects.
Also your Response
size is around 5.96 MB
. This is too big response. Instead of receiving this much of data in single response you could implement pagination or something similar to break down data. This could be one of the reason.
回答4:
//Your Main connection Class
public class ApiClient {
public static final int DEFAULT_TIMEOUT_SEC = 90;
public static OkHttpClient client;
private static Retrofit retrofit = null;
public static Retrofit getClient() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIMEOUT_SEC, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIMEOUT_SEC, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIMEOUT_SEC, TimeUnit.SECONDS);
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
System.out.println("API_KEY"+PrefManager.getActiveInstance(RecrouteCandidateApplication.getsCurrentContext()).getDeviceToken());
Request request = original.newBuilder()
.header("x-access-token",YOUR_ACCESS_TOKEN"")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
//For logging the call on Logcat
HttpLoggingInterceptor interceptor1 = new HttpLoggingInterceptor();
interceptor1.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(interceptor1);
client = httpClient.build();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(AppConstants.BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Use in Your Class which will initiate the connection like this
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
And This will be your ApiInterface
public interface ApiInterface {
@POST("Your url here")
Call<JsonObject> sampleMethod();
/*For non-empty body use this*/
//Call<JsonObject> getSignUpResponse(@Body JsonObject register);
//For form data use this
@FormUrlEncoded
@POST("Your url here")
Call<String> sampleMethod1(@Field(value= "param1_key", encoded = true) String param1_value);
}
Make a call like this for json
JsonObject obj= new JsonObject();
obj.addProperty("key1","keyvalue");
Call<JsonObject> call = apiService.sample1(obj);
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.body().get("status").getAsString().equals("1")) {
Toast.makeText(context, response.body().get("msg").getAsString(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, response.body().get("msg").getAsString(), Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Toast.makeText(context, AppConstants.NO_DATA_AVAILABLE, Toast.LENGTH_LONG).show();
}
});
回答5:
for me the problem was because I had this line in the Gson builder :
.excludeFieldsWithoutExposeAnnotation()
with the above line, all the fields in your model classes that you send as body in retrofit will be ignored if they are not annotated with the @Exposed
annotation.
removing .excludeFieldsWithoutExposeAnnotation()
solved the problem for me.
来源:https://stackoverflow.com/questions/47375322/retrofit-gets-400-bad-request-but-works-with-postman