I'm trying to send a request to a NodeJS server, I'm always getting Bad Request message with status code 400.
I tried using Postman to check if the problem was on the server, but in Postman it worked correctly.
I'm using OkHttp and trying to send a request like this:
private Request request;
private final OkHttpClient client = new OkHttpClient();
private void makePost(String nameOfProduct, String serialOfProduct, String priceOfProduct, String gender, String uriList, String colors, String sizes) {
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("name", nameOfProduct)
.addFormDataPart("serial",serialOfProduct)
.addFormDataPart("price",priceOfProduct)
.addFormDataPart("gender",gender)
.addFormDataPart("color", colors)
.addFormDataPart("size", sizes)
.addFormDataPart("imagesUri",uriList)
.build();
Log.d("COLROS", colors);
request = new Request.Builder()
.url("http://10.0.2.2:4000/products/add")
.header("Content-Type", "application/json")
.post(requestBody)
.build();
try{
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
Headers responeHeaders = response.headers();
for (int i = 0; i < responeHeaders.size(); i++) {
Log.d("iu", "makePost: "+responeHeaders.name(i) + ": " + responeHeaders.value(i));
}
Log.d("iu", "makePost: "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
You are sending Form data (application/x-www-form-urlencoded) but setting the header as json
Try to remove the line:
.header("Content-Type", "application/json")
and use:
.header("Content-Type", "application/x-www-form-urlencoded")
To send JSON data, you must build a JSON string. I'll use Gson library here, make sure you include it in your module level gradle file as follows:
implementation 'com.google.code.gson:gson:2.8.6'
Next you need a class to serialize into JSON:
public class Order {
public String name;
public String serial;
public int price;
public String gender;
//Other fields go here...
//This empty constructor is required by Gson
public Order() {}
}
Now you build an object of this class as you require:
private void makePost(String nameOfProduct, String serialOfProduct, String priceOfProduct, String gender, String uriList, String colors, String sizes) {
Order order = new Order();
order.name = nameOfTheProduct;
order.price = priceOfTheProduct;
//Fill in other fields here...
//Now get a JSON data string from this object using Gson:
Gson gson = new Gson();
String jsonData = gson.toJson(order);
public static final MediaType mediaTypeJSON = MediaType.get("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaTypeJSON, jsonData);
//Build the request
Request request = new Request.Builder()
.url("http://10.0.2.2:4000/products/add")
.post(requestBody)
.build();
//Finally send the request as you already do in your code
//Using the call: Response response = client.newCall(request).execute();
}
Related
I want to pass dynamic value inside request body in my case I pass
thirdpartypaymentGatewayToken in two place inside request body and an
other place requestString as requestBody but I want make single
function and pass values inside request body dynamic. for your
reference I post my old code and new code.
Here my old code
public ThirdPartyPaymentGatewayResponse getThirdPartyPaymentGatewayToken(ThirdPartyPaymentGatewayToken thirdPartyPaymentGatewayToken, String managedBy)
throws AuthenticationException, UnknownHostException, BadRequestException {
String brandwiseBearerToken = getBrandwiseAuthenticationToken();
ThirdPartyPaymentGatewayResponse thirdPartyPaymentGatewayResponse = new ThirdPartyPaymentGatewayResponse();
String thirdPartyPaymentGatewayTokenJson = ow.writeValueAsString(thirdPartyPaymentGatewayToken);
RequestBody body = RequestBody.create(mediaType, thirdPartyPaymentGatewayTokenJson);
Request request = new Request.Builder().url(brandwiseThirdPartypaymentGatewayURL)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Bearer", brandwiseBearerToken)
.build();
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
JsonObject jsonObject = new Gson().fromJson(responseBody.string(), JsonObject.class);
JsonElement error = jsonObject.get("Message");
}
> second function
public ThirdPartyPaymentGatewayResponse getThirdPartyPaymentGatewayToken(ThirdPartyPaymentGatewayToken thirdPartyPaymentGatewayToken, String managedBy)
throws AuthenticationException, UnknownHostException, BadRequestException {
String brandwiseBearerToken = getBrandwiseAuthenticationToken();
String thirdPartyPaymentGatewayTokenJson = ow.writeValueAsString(thirdPartyPaymentGatewayToken);
RequestBody body = RequestBody.create(mediaType, thirdPartyPaymentGatewayTokenJson);
Request request = new Request.Builder().url(brandwiseThirdPartypaymentGatewayURL)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Bearer", brandwiseBearerToken)
.build();
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
JsonObject jsonObject = new Gson().fromJson(responseBody.string(), JsonObject.class);
JsonElement error = jsonObject.get("Message");
/** rest of code*/
}
third function different than other two
private String getBrandwiseAuthenticationToken() throws UnknownHostException, AuthenticationException {
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
String requestString = "{\"LoginName\": \"" + brandwiseAuthUsername + "\",\"Password\": \""+ brandwiseAuthPassword + "\"}";
RequestBody body = RequestBody.create(mediaType, requestString);
Request request = new Request.Builder().url(brandwiseAuthenticationURL)
.post(body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
JsonObject jsonObject = new Gson().fromJson(responseBody.string(), JsonObject.class);
}
To overcome from this issue I do this way but I am not able make
request body as dynamic. Here my new code
private JsonObject gateWayToken(String url,String brandwiseBearerToken,
ThirdPartyPaymentGatewayToken thirdPartyPaymentGatewayToken ) throws IOException, AuthenticationException{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String requestString = "{\"LoginName\": \"" + brandwiseAuthUsername + "\",\"Password\": \""+ brandwiseAuthPassword + "\"}";
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body=null;
//dynamic value accept by body
if(!Strings.isNullOrEmpty(requestString)) {
String brandwiseBearerPaymentGatewayTokenJson = ow.writeValueAsString(requestString);
body = RequestBody.create(mediaType,brandwiseBearerPaymentGatewayTokenJson);
}else {
String thirdPartyPaymentGatewayTokenJson = ow.writeValueAsString(thirdPartyPaymentGatewayToken);
body = RequestBody.create(mediaType,thirdPartyPaymentGatewayTokenJson );
}
//if user is authenticated then header part will show
Request request=null;
if (brandwiseBearerToken != null && StringUtils.isNotEmpty(brandwiseBearerToken)) {
request =new Request.Builder().url(url).post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Bearer", brandwiseBearerToken)
.build();
} else {
request=new Request.Builder().url(url).post(body)
.addHeader("Content-Type", "application/json")
.build();
}
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
return new Gson().fromJson(responseBody.string(), JsonObject.class);
}
I want to dynamic exact at this point
if(!Strings.isNullOrEmpty(requestString)) {
String brandwiseBearerPaymentGatewayTokenJson = ow.writeValueAsString(requestString);
body = RequestBody.create(mediaType,brandwiseBearerPaymentGatewayTokenJson);
}else {
String thirdPartyPaymentGatewayTokenJson = ow.writeValueAsString(thirdPartyPaymentGatewayToken);
body = RequestBody.create(mediaType,thirdPartyPaymentGatewayTokenJson );
}
Check Passing values inside ReqestBody
I am connecting black box backend, I have no control over the source and cannot modify the backend, using Ok Http 3. But for some reason, I am getting two results and I don't know what's going on. I suspect two threads are becoming active. But I don't know how to stop it. I tried both Synchronous and Asynchronous connection to no effect. I am new to Ok Http 3, so I am not sure what I am doing wrong.
I/Results: {"TotalResultsCount":3,"Results":[{
I/Results: {"TotalResultsCount":24,"Results":[
Here's is my synchronous code
class CallBackendSync extends AsyncTask {
OkHttpClient client = new OkHttpClient();
JSONObject resultsObject = null;
#Override
protected Object doInBackground(Object [] objects) {
String searchTerm = (String) objects[0];
String url = (String) objects[1];
String token = (String) objects[2];
String results = "";
//Search Body
RequestBody searchBody = new FormBody.Builder()
.add("QueryText", searchTerm)
.add("Categories", "")
.add("ChargeOutPerMinuteFrom", "0")
.add("ChargeOutPerMinuteTo", "0")
.add("maxDistance", "0")
.add("longitude", "0")
.add("latitude", "0")
.add("page", "0")
.build();
//Create request
Request.Builder builder = new Request.Builder();
builder.url(url);
builder.addHeader("Accept", "application/json");
if (token != null) {
builder.addHeader("Authorization", token);
}
builder.post(searchBody);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
results = results + response.body().string();
resultsObject = new JSONObject(results);
Log.i("Results", results);
return resultsObject;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String s){
super.onPostExecute(s);
displayResults(resultsObject);
}
}
I am calling the backend from MainActivity using the code fragment below
CallBackendSync sync = new CallBackendSync();
String [] params = {searchTerm, serverBaseUrl + url, accessToken};
sync.execute(params);
Any ideas about what's going wrong will be much appreciated.
I have four static parameters which i need to set to every post retrofit request only once, because i don't need to put them with every request every time. This is my code:
public interface Login {
#POST("login")
#Headers("Content-Type: application/json")
Call<String> login(#Body JsonObject json);
}
then i call it and pass email and password as body parameters like this:
private void sendLoginRequest() {
API.login().login(CommandLogin.getInputParamsAsJSON(mStrEmail, Utils.md5(mStrPassword))).enqueue(this);
}
then in intercept body i tried to pass this static parameters, but when i check the log it seems to pass only this two static params without email and password. In my situation i want to put in body email,password,os,version.
public class API {
private static <T> T builder(Class<T> endpoint) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain){
try {
Request original = chain.request();
JSONObject params = new JSONObject();
params.put("version" , "6");
params.put("os" , "2");
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, params.toString());
Request.Builder requestBuilder = original.newBuilder()
.post(body);
Request request = requestBuilder.build();
return chain.proceed(request);
} catch (Exception e) {
e.printStackTrace();
}
//TODO
return null;
}
})
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
return new Retrofit.Builder()
.baseUrl(Utils.BASE_COMPONENT_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
.create(endpoint);
}
public static Login login() {
return builder(Login.class);
}
}
That's because, you are basically overwriting original Login Post Request Body with new params. What you should do instead is, get the post body from original request and append new params to it.
Something like below (code not tested)
try {
// Create new buffer
final Buffer buffer = new Buffer();
// Copy original request's json body to buffer
chain.request().body().writeTo(buffer);
// Convert buffer to JSONObject
JSONObject params = new JSONObject(buffer.readUtf8());
// Append new params
params.put("version", "6");
params.put("os", "2");
// Now the params json object will have all 4 values: email,password,os,version
// TODO: Your remaining code
} catch (Exception ex) {
Log.d("Login","Error creating post body", ex);
}
I want to use Spring RestTemplate instead of Apache HttpClient for working with a remote API
With HttpClient
// build request JSON
JSONObject json = new JSONObject();
json.put("username", username);
json.put("serial", serial);
json.put("keyId", keyId);
json.put("otp", otp);
String json_req = json.toString();
// make HTTP request and get response
HttpPost request = new HttpPost(AuthServer);
request.setHeader("Content-Type", "application/json");
request.setEntity(new StringEntity(json_req));
response = client.execute(request);
With RestTemplate
Map<String, String> paramMap = new HashMap<String,String>();
paramMap.put("username", userName);
paramMap.put("serial", serial);
paramMap.put("keyId", keyId);
paramMap.put("otp", otp);
String mapAsJson = new ObjectMapper().writeValueAsString(paramMap);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<String>(mapAsJson,requestHeaders);
try {
ResponseEntity<String> response = restTemplate.exchange(AuthServer, HttpMethod.POST, request, String.class);
return response.getHeaders();
} catch (HttpClientErrorException e) {
return null;
}
}
The code with HttpClient works but that with RestTemplate does not. I don't know how to use StringEntity in RestTemplate.
Spring version is 3.0.0, and JVM is 1.6.
RestTemplate is better suited to working with objects. As an example:
AuthenticationRequest.java
class AuthenticationRequest {
private String username;
private String serial;
private String key;
private String otp;
}
AuthenticationResponse.java
class AuthenticationResponse {
private boolean success;
}
AuthenticationCall.java
class AuthenticationCall {
public AuthenticationResponse execute(AuthenticationRequest payload) {
HttpEntity<AuthenticationRequest> request = new HttpEntity<AuthenticationRequest>(payload, new HttpHeaders());
return restTemplate.exchange("http://www.domain.com/api/endpoint"
, HttpMethod.POST
, request
, AuthenticationResponse.class).getBody();
}
}
These classes can be used as follows:
if(new AuthenticationCall().execute(authenticationRequest).isSuccess()) {
// Authentication succeeded.
}
else {
// Authentication failed.
}
All of this requires there to be a JSON library such as Jackson or GSON on the classpath.
How can I post data from my android app to php server with okhttp? Is it even possible? I've been able to retrieve data from the server, but I need to send String from my application to the server.
Thanks.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestUrl).build();
Call call = client.newCall(request);
try {
Response response = call.execute();
if(response.isSuccessful()){
Log.v("LOGV", response.body().string());
}
} catch (IOException e) {
e.printStackTrace();
Log.v("LOGV", e.getMessage().toString());
}
Here is example from okhttp website:
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8"); //defines the type of the body
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body) //include the body in the request with the POST method
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
And a link to their github repo with similar example: https://raw.githubusercontent.com/square/okhttp/master/samples/guide/src/main/java/com/squareup/okhttp/guide/PostExample.java