Reputation: 43
I'm using Retrofit2. Send a POST request with body (as a JSON array), but getting the "400 Bad Request". Meanwhile sending the request from SoapUI and my http client (based on HttpURLConnection) works fine.
API Interface for the service:
public interface ApiService {
@POST( "let/fmir" )
@Headers( {
"Accept-Encoding: gzip,deflate",
"Content-Type: Application/Json;charset=UTF-8",
"Accept: Application/Json",
"User-Agent: Retrofit 2.3.0"
} )
Call<LetPOJO> fmir(
@Header( "Authorization" ) String authorization,
@Body String body
);
}
API service provider:
public class ApiServiceProvider {
public ApiService createApiService() {
// Prepare the Retrofit logger
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor( interceptor).build();
// Build the Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl( "http://1.1.1.1:3040/api/v1.0/" )
.client( client )
.addConverterFactory( JacksonConverterFactory.create() );
.build();
return retrofit.create( ApiService.class );
}
}
Invoke service by declared API (input data were obfuscated):
ApiService apiService = ApiServiceProvider.createApiService();
Call<LetPOJO> call = apiService.fmir(
"Basic NDUhg4234OQ==",
"[\"L___1\",\"L___2\",\"L___3\",\"L___4\"]"
);
Log of Retrofit interceptor:
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: --> POST http://1.1.1.1:3040/api/v1.0/let/fmir
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: Content-Type: Application/Json;charset=UTF-8
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: Content-Length: 139
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: Accept-Encoding: gzip,deflate
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: Accept: Application/Json
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: User-Agent: Retrofit 2.3.0
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: Authorization: Basic NDUhg4234OQ==
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO:
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: "[\"L___1\",\"L___2\",\"L___3\",\"L___4\"]"
янв 24, 2018 10:12:38 AM okhttp3.internal.platform.Platform log INFO: --> END POST (139-byte body)
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: <-- 400 Bad Request http://1.1.1.1:3040/api/v1.0/let/fmir (121ms)
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Vary: Accept-Encoding
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Content-Encoding: gzip
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Content-Type: text/plain
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Date: Wed, 24 Jan 2018 07:12:39 GMT
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Connection: close
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: Content-Length: 192
янв 24, 2018 10:12:39 AM okhttp3.internal.platform.Platform log INFO: <-- END HTTP (encoded body omitted)
Response's Content-Type is text/plain, but expected Application/Json
For example, working SoapUI's request/response: The request:
POST http://1.1.1.1:3040/api/v1.0/let/fmir HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/json;charset=UTF-8
Authorization: Basic NDUhg4234OQ==
Content-Length: 129
Host: 1.1.1.1:3040
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
And its response:
HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Type: application/json
Date: Wed, 24 Jan 2018 08:33:12 GMT
Content-Length: 689
[{"id":"L___1"}]
The body is obfuscated also. As we can see Content-Type: application/json
When I sending via HttpURLConnection - HTTP headers of the request are the same also and works fine:
However, GET request with Queries works fine via Retrofit.
I not found any solutions for this problem. In some cases propose to use @Header
annotation as a method argument - but behaviour is the same.
This is the server endpoint:
@ApiOperation("Some description")
@POST @Path("fmir")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "ОК"),
@ApiResponse(code = 400, message = "some message"),
@ApiResponse(code = 500, message = "some message")
})
public List<Letter> getLet(
@ApiParam(value = "Authorization header")
@HeaderParam(HttpHeaders.AUTHORIZATION) final String authorization,
@Context ContainerRequestContext context,
final List<String> letterIds) {
// ...
}
Upvotes: 4
Views: 11191
Reputation: 170138
Since the server endpoint expects a list of strings, I think your client will need to send this as well (an not send a string):
So, try this:
public interface ApiService {
@POST( "let/fmir" )
@Headers( {
"Accept-Encoding: gzip,deflate",
"Content-Type: Application/Json;charset=UTF-8",
"Accept: Application/Json",
"User-Agent: Retrofit 2.3.0"
} )
Call<LetPOJO> fmir(
@Header( "Authorization" ) String authorization,
@Body List<String> body
);
}
...
ApiService apiService = ApiServiceProvider.createApiService();
Call<LetPOJO> call = apiService.fmir(
"Basic NDUhg4234OQ==",
Arrays.asList("L___1", "L___2", "L___3", "L___4")
);
Upvotes: 3