Generated by swagger code for android for volley library incorrect handles post requests with json body. When I use api method with json body, I receive an error response with status = 400 and message "Invalid header". The problem is in this code fragment in ApiInvoker class:
request = new PostRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
By default in my case code
new StringEntity(serialize(body), "UTF-8")
creates an entity with text/plain content type. That is wrong because server expects application/json content type.
To fix it is sufficient to replace code
request = new PostRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
by
StringEntity entity = new StringEntity(serialize(body),"UTF-8");
entity.setContentType("application/json");
request = new PostRequest(url, headers, contentType, entity, stringRequest, errorListener);
@rasuldev in your spec, have you set a proper consumes for the POST JSON body operation?
For Android, you can also use the Java API client: https://github.com/swagger-api/swagger-codegen/wiki/FAQ#how-can-i-generate-an-android-sdk
@wing328 yes, I set application/json for consumes.

Full json spec can be found here. Mentioned in first comment error raises in method api/account/register.
@rasuldev thanks for providing more details. Can you try the Java (okhttp-gson or retrofit2) API client to see if it has similar issue?
@rasuldev do you need help generating Java API client (okhttp-gson, retrofit2)?
Closing this as there's no update.
Having the same issue.
A simple POST that swagger.yaml declares as consumes "application/json" is sent to server with two content types.
From WireShark "copy as plain text" of the http packet:
POST /api/things HTTP/1.1
Accept: application/json
User-Agent: Swagger-Codegen/1.0.0/android
Content-Type: application/json
Content-Type: text/plain; charset=UTF-8
...
Debugging using Android studio, I see that for POST methods, HurlStack.addBodyIfExists()is called, and for POSTs with a body (which most POSTs have), it calls
connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType());
request.getBodyContentType() takes the content type from the request's org.apache.http.HttpEntity. The instance of the HttpEntity is actually a StringEntity, which returns a text/plain content type by default.
the fix suggested by @rasuldev will possibly work with other servers, but does not work with swagger-generated "jaxrs" server. The reason is that there are 2 lines with Content-Type: application/json in the request.
POST /api/things HTTP/1.1
Accept: application/json
User-Agent: Swagger-Codegen/1.0.0/android
Content-Type: application/json
Content-Type: application/json
...
Sounds like the correct fix is to change io.swagger.client.request.PostRequest to include only one content-type. It currently has two: one in field contentType and another in field HttpEntity.
For now, I locally changed PostRequest to return the content-type of contentType when asked for the body's content-type (could have used the suggestion from @rasuldev but had to also change the contentType sent to the PostRequest c'tor to null)
replaced
public String getBodyContentType() {
if(entity == null) {
return null;
}
return entity.getContentType().getValue();
}
...
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
if (apiHeaders != null && !apiHeaders.equals(Collections.emptyMap())) {
headers.putAll(apiHeaders);
}
if(contentType != null) {
headers.put("Content-Type", contentType);
}
return headers;
}
with:
public String getBodyContentType() {
if (contentType != null) {
return contentType;
}
if(entity == null) {
return null;
}
return entity.getContentType().getValue();
}
...
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
if (apiHeaders != null && !apiHeaders.equals(Collections.emptyMap())) {
headers.putAll(apiHeaders);
}
if((entity == null) && (contentType != null)) {
headers.put("Content-Type", contentType);
}
return headers;
}
and now it works :)
POST /api/things HTTP/1.1
Accept: application/json
User-Agent: Swagger-Codegen/1.0.0/android
Content-Type: application/json
...
and getting HTTP 200
@kfirwolfson description is precise. @wing328 can we re-open?
The problem is in this StringEntity constructor, where for request = new PostRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener); ContentType.TEXT_PLAIN.getMimeType() is enforced. And then HurlStack allows two ContentType headers to be present.
I have hit this same problem. I'm using an IIS server and having two Content-Type headers throws a failure.
It would be great if this issue could be reopened and the the generated code updated so I don't have to modify it after every codegen.
Incidentally, my solution was to change:
request = new PostRequest(url, headers, contentType, new StringEntity(serialize(body), "UTF-8"), stringRequest, errorListener);
to
request = new PostRequest(url, headers, null, new StringEntity(serialize(body), APPLICATION_JSON), stringRequest, errorListener);
This resulted in just the one content type being added.
Most helpful comment
Having the same issue.
A simple POST that swagger.yaml declares as consumes "application/json" is sent to server with two content types.
From WireShark "copy as plain text" of the http packet:
Debugging using Android studio, I see that for POST methods,
HurlStack.addBodyIfExists()is called, and for POSTs with a body (which most POSTs have), it callsrequest.getBodyContentType()takes the content type from the request'sorg.apache.http.HttpEntity. The instance of theHttpEntityis actually aStringEntity, which returns atext/plaincontent type by default.the fix suggested by @rasuldev will possibly work with other servers, but does not work with swagger-generated "jaxrs" server. The reason is that there are 2 lines with
Content-Type: application/jsonin the request.Sounds like the correct fix is to change
io.swagger.client.request.PostRequestto include only one content-type. It currently has two: one in fieldcontentTypeand another in fieldHttpEntity.For now, I locally changed
PostRequestto return the content-type of contentType when asked for the body's content-type (could have used the suggestion from @rasuldev but had to also change the contentType sent to the PostRequest c'tor to null)replaced
with:
and now it works :)
and getting
HTTP 200