code 400 error on post call with android - java

I am trying to call a WS method from an Android application with POST method.
What I have done:
String urlServer = GlobalSession.IP + "insert_reportByte";
Log.d("[Report]", "url address: " + urlServer);
URL url = new URL(urlServer);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type",
"multipart/form-data");
DataOutputStream outputStream = new DataOutputStream(
connection.getOutputStream());
outputStream.write(outputByteArray, 0, outputByteArray.length);
int serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
Log.d("ServerCode", "" + serverResponseCode);
Log.d("serverResponseMessage", "" + serverResponseMessage);
outputStream.flush();
outputStream.close();
} catch (Exception ex) {
// ex.printStackTrace();
Log.e("[Report] --- /!\\ Error: ", ex.getMessage());
}
return result;
So I am supposed to send a byte array to the service. But I have a 400 error response. My question is: how to get the details of such an issue? Because I cannot find anything in the logs of the server and it's hard to debug if I do not have the details...
The WS is defined (in ASP.NET) that way:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "insert_reportByte",
BodyStyle = WebMessageBodyStyle.Bare)]
void insert_reportByte(byte[] image);
And the called method is the following
public void insert_reportByte(byte[] image)
{
MyEntities entities = new MyEntities();
String base64stringimage = System.Convert.ToBase64String(image,0,image.Length);
entities.insert_report("admin", "0614141.107346.2001", "test", base64stringimage, "test");
}
What did I do wrong?
Thank you !

You should change the uploadReadAheadSize and maxReceivedMessageSize parameters on your server applicationHost.config file.
Here you´ve got a thread that talks about it
http://forums.iis.net/t/1169257.aspx?Request+Entity+Too+large+413+error+
This link might be useful too as it explains why you should change the uploadReadAheadSize and maxReceivedMessageSize parameters for better handling of file uploads.
http://www.codeproject.com/Articles/521725/413-Request-Entity-Too-Large
UPDATE
Try using this library for the http calls. It seems that you're sending a bad request to the server. I don't think it has something to do with the parameters that the ws expects but the http headers sent by the android app.
https://github.com/loopj/android-async-http
Hope it helps. :)

Related

PATCH Request in Java using MSAL (msal-client-credential-secret)

I'm using client credential secret to run API on Microsoft Endpoint (Intune).
Example used from link.
Getting access token. (Working)
Get android Managed App Protections. (Working using GET HTTP Method)
Patch Request. (Not Working)
The examples do not mention any PATCH or POST request, hence need some help for it.
I tried the below code snippet but it fails.
private void setAndroidModels(final String accessToken, final String policyId, final String modelList)
throws IOException {
URL url = new URL(
"https://graph.microsoft.com/beta/deviceAppManagement/androidManagedAppProtections/" + policyId);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("PATCH");
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
byte[] input = modelList.getBytes();
os.write(input, 0, input.length);
}
int httpResponseCode = conn.getResponseCode();
System.out.println("POST Response Code : " + httpResponseCode);
System.out.println("POST Response Message : " + conn.getResponseMessage());
}
Result : Exception in thread "main" java.net.ProtocolException: Invalid HTTP method: PATCH
Also tried
private void setAndroidModels(final String accessToken, final String policyId, final String modelList)
throws IOException {
URL url = new URL(
"https://graph.microsoft.com/beta/deviceAppManagement/androidManagedAppProtections/" + policyId);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("X-HTTP-Method-Override", "PATCH");
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
byte[] input = modelList.getBytes();
os.write(input, 0, input.length);
}
int httpResponseCode = conn.getResponseCode();
System.out.println("POST Response Code : " + httpResponseCode);
System.out.println("POST Response Message : " + conn.getResponseMessage());
}
Result :
POST Response Code : 400
POST Response Message: Bad Request
How can I get the client credential secret logic working for POST and PATCH HTTP Methods?
We can directly call patch request in MS Graph.
When creating PATCH requests to the API, you need to create a new
PATCH object that contains only the information you want to update.
This should be distinct from any objects you receive from the service
from a GET or a POST.
Please refer Document for more details.
For example, Patch rquest to user
User realMe = graphClient.me().buildRequest().get();
User patchMe = new User();
patchMe.givenName = "Beth";
realMe = graphClient
.users(realMe.userPrincipalName)
.buildRequest()
.patch(patchMe);

FileNotFoundException on getInputStream from GAE address

I'm doing an Android app with an API with Python. The API is on a Google App Engine cloud and everything works fine when I tested it with Postman.
I'm trying to do a Login with a POST method. That method returns json with the user information I keep getting that error: FileNotFoundException
Here is some of my code:
try{
String account = params[0].get(0);
String password = params[0].get(1);
URL url = new URL("http", WEB_SERVICE_URL, PORT, REST_LOGIN);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(CONNECTION_TIMEOUT);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Accept", "application/json");
JSONObject json = jsonParser.serialJsonLogin(nomCompte, motPasse);
osw = new OutputStreamWriter(httpURLConnection.getOutputStream(),"UTF-8");
osw.write(json.toString());
osw.flush();
String body = readStream(httpURLConnection.getInputStream());
osw.close();
Log.i(TAG, "Return : " + body);
user = jsonParser.deserializeJsonUser(body);
}catch (Exception e) {
mException = e;
}finally {
if (mHttpURLConnection != null) {
mHttpURLConnection.disconnect();
}
}
return user;
At: String body = readStream(httpURLConnection.getInputStream()); I'm getting a java.io.FileNotFoundException: http://10.0.2.2:8080/login
My readStream method is fine, I tested it. If I look in my Google App Engine logs, I can see that there is no 404, or anything wrong. If I find the user I get a 201 if not a 403. So even if the error says FileNotFound, I see status code which means that actually the URL is right.
UPDATE: My API was giving me a 201 and getInputStream apparently doesn't work on 201 status. Changed my return status to 200 in my API and it works fine.

GCM Push Notifications are not delivered to devices

We (Panos and Rainer - see the comments down) have a server and several Android devices.
We want to send push notifications from our server via GCM to the Android devices.
Now we make a post request to the GCM server. The GCM server response is that all is fine (success==1 and even the message-id)!
BUT the push notification(s) are never delivered to the devices.
If we use the same data and the Chrome addon Postman - the notifications are delivered immediately.
We tried all lot of different solutions. We get always the feedback of the GCM server that all is ok - but the push notifications aren't send.
We also tried this one:
https://github.com/googlesamples/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java
You might also post the URL you use. There is a new GCM enpoint which looks like the following:
https://gcm-http.googleapis.com/gcm/send
I am not yet sure what's causing the issues on your side. But the following is tested and working:
public class Main {
public static void main(String[] args) {
// write your code here
try {
String url = "https://gcm-http.googleapis.com/gcm/send";
URL obj = new URL(url);
HttpsURLConnectionImpl conn = (HttpsURLConnectionImpl) obj.openConnection();
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty ("Authorization", "key=***");
String title = "Short title";
String body = "A body :D";
String token = "****";
String data = "{ \"notification\": { \"title\": \"" + title +"\", \"body\": \"" + body + "\" }, \"to\" : \"" + token + "\", \"priority\" : \"high\" }";
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(data);
out.close();
String text = getText(new InputStreamReader(conn.getInputStream()));
System.out.println(text);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getText(InputStreamReader in) throws IOException {
StringBuilder sb=new StringBuilder();
BufferedReader br = new BufferedReader(in);
String read;
while((read=br.readLine()) != null) {
sb.append(read);
}
br.close();
return sb.toString();
}
}
This is the data used for the Postman request which is working without any problem.
Rainer already mentioned that we tried several implementations on the Java side and it seems that we are always able to communicate with the service and receive a response which seems to look correct so far:
{
"multicast_id":7456542468425129822,
"success":1,
"failure":0,
"canonical_ids":0,
"results":
[{
"message_id":"0:1457548597263237%39c590d7f9fd7ecd"
}]
}
Not sure if I'm on the right track but do you mean downstream HTTP messages (plain text)?
Tried to send the following JSON to the service (from Postman) which results again in a positive response but this time the notification did not reach the device (just to make that clear, at the moment there is no app on the device listening actively for incoming notifications -> first of all we just want to ensure that they generally arrive on the device):
{
"data":
{
"score": "5x1",
"time": "15:10"
},
"to" : "SECRET-DEVICE-TOKEN"
}
Thanks to all of you trying to help here but to be honest, this issue is really frustrating. Communicating with an interface\service which seems not to be able to return a useful response in case the request contains maybe evil stuff which will finally prevent GCM from sending the push notification to the device, feels like a pain in the ass. If Postman would also fail I would say ok, you can not be so stupid :-)
Here are some quick'n dirty implementations we have already used.
Example
try
{
URL url = new URL(apiUrl);
HttpsURLConnection conn = (HttpsURLConnection);//also tried HttpURLConnection
url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key="+apiKey);
conn.setDoOutput(true);
String json = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
OutputStream os = conn.getOutputStream();
os.write(json.getBytes());
os.flush();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
HttpClient httpClient = HttpClientBuilder.create().build();
try
{
HttpPost request = new HttpPost(apiUrl);
StringEntity params =new StringEntity("{\"priority\":\"high\",\"notification\":{\title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}");
request.addHeader("Content-Type", "application/json");
request.addHeader("Authorization", "key="+apiKey);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// check response
System.out.println(response.getStatusLine().toString());
}catch (Exception exc) {
System.out.println("Error while trying to send push notification: "+exc);
} finally {
httpClient.getConnectionManager().shutdown(); //Deprecated
}
Example
try
{
String charset = "UTF-8";
URLConnection connection = new URL(apiUrl).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
connection.setRequestProperty("Authorization", "key="+apiKey);
String param = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
try (OutputStream output = connection.getOutputStream())
{
output.write(param.getBytes(charset));
}
InputStream response = connection.getInputStream();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
try
{
// prepare JSON
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("message", "{ \"data\": {\"score\": \"5x1\",\"time\": \"15:10\"},\"to\" : \""+deviceToken+"\"}");
jGcmData.put("to", deviceToken);
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + apiKey);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
// Read GCM response.
InputStream inputStream = conn.getInputStream();
String resp = IOUtils.toString(inputStream);
System.out.println(resp);
} catch (IOException e) {
System.out.println("Unable to send GCM message. "+e);
}
Mike, with your example it's working also on our side. After comparing your implementation with the on eon our side, the only real difference I found is the used URL!!
Somehow the URL used in our Java implementation was https://android.googleapis.com/gcm/send
Seems that https://gcm-http.googleapis.com/gcm/send is the right one which by the way was also used for our Postman tests.
But why on hell is the URL from our failed tests still somehowe valid and returns a response!?
Setting the priority to high in the json resolved the issue for me.
'registration_ids' => $id,
'priority' => 'high',
'data' => $load
For our case, the clients Android devices had intermittent internet connection issue, that is, network dropouts thus causing notification delivery failed. We resolved the reliability issue with the following JAVA GCM code:
gcmPayload.setTime_to_live(messageExpiryTime); //in seconds. Set notification message expiry to give user time to receive it in case they have intermittent internet connection, or phone was off
gcmPayload.setPriority("high");
and APNS code:
ApnsService apnsService = APNS.newService().withCert(certificateStream, configurations.getApnPassword()).withProductionDestination().build();
PayloadBuilder payloadBuilder = APNS.newPayload();
...
payloadBuilder.instantDeliveryOrSilentNotification(); //same as content-available=true
String payload = payloadBuilder.build();
Integer now = (int)(new Date().getTime()/1000);
//use EnhancedApnsNotification to set message expiry time
for(String deviceToken : deviceTokens) {
EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID() /* Next ID */,
now + messageExpiryTime /* Expiry time in seconds */,
deviceToken /* Device Token */,
payload);
apnsService.push(notification);
}
Also, remember to consider time zone if your backend server time is different to the client mobile app time.

HttpsUrlConnection with Authorization seems to cut off url parameter in GET request

I'm trying to establish a Connection via HTTPS. I also set the "Authorization" property in the Request Header to Basic and provide an encoded auth string accordingly.
I checked with the Firefox Plugin HttpRequester and everythign works fine, which means I entered the url, choose "GET" as request method, add the Authorization to the header and after pressing submit I get back some xml which only a properly authorized user should get.
Unfortunately I can neither provide you with the actual auth info nor the real url in the SSCCE. However, I can tell you, that the Auth seems to work, since I get a 200 response. I also changed the Auth to a wrong value and get a "401 Authorization Required" response then.
It actually seems like the "?myparam=xyz" is somehow cut off, because when I remove this parameter from the url and test with Firefox HttpRequester again I get the same response as in Java.
Unfortunately I have no access to "theirdomain.com", so I don't know what's happending on the server side. But since it works with the Firefox HttpRequester, it should also work with Java.
What could be the reason? Thanks for your help!
EDIT:
I changed the url to "https://www.google.com/search?q=foo" and commented this line:
//con.setRequestProperty("Authorization", auth);
I can see from the returned string, that google received the "foo". So apparently the combination of Authorization and get parameter seems to be the problem, since both separately work fine.
SSCCE:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class HttpRequest
{
/**
* #param args
*/
public static void main(final String[] args)
{
System.out.println("start request");
final String urlString = "https://theirdomain.com/foo/bar/bob?myparam=xyz";
final String auth = "Basic XyzxYzxYZxYzxyzXYzxY==";
HttpsURLConnection con;
try
{
final URL url = new URL(urlString);
con = (HttpsURLConnection) url.openConnection();
con.setRequestProperty("Authorization", auth);
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");
con.setRequestMethod("GET");
// con.setDoOutput(true);
con.connect();
final int responseCode = con.getResponseCode();
if (responseCode != 200)
System.out.println("Server responded with code " + responseCode + " " + con.getResponseMessage());
else
{
System.out.println("Starting to read...");
final InputStream inStream = con.getInputStream();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
int c;
while (inStream != null && (c = inStream.read()) != -1)
{
baos.write(c);
}
System.out.println(new String(baos.toByteArray()));
}
}
catch (final IOException e)
{
System.out.println("could not open an HTTP connection to url: " + urlString);
e.printStackTrace();
}
finally
{
System.out.println("end request");
}
}
}
Have you tried adding
con.setRequestProperty("myparam", "xyz"); to your code?

Http POST in BlackBerry

Greetings,
I am trying to setup a server connection from my BlackBerry Application . I was able to get a response code on the status of the server. Now i have a few values which i have to POST to the server
Its like a registration page values(username, password, age ) have to be sent to the server .
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(url);
if (connDesc != null)
{
HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
final int iResponseCode = httpConn.getResponseCode();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Dialog.alert("Response code: " + Integer.toString(iResponseCode));
}
});
}
catch (IOException e)
{
System.err.println("Caught IOException: " + e.getMessage());
}
}
Thats the code i used to get the response code.
I would appreciate it if someone could help me how i can make a POST request to the server..
the server url for status was company.com/app/version/stats
when it for register it would be
company.com/app/register
Thank you
What type of a POST do you use? If you are just passing key-value pairs, then it should be a POST of a "application/x-www-form-urlencoded" content-type.
So, what lacks youe code is:
1). Set a proper content-type on your connection:
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
2). Prepare the content to be sent to the server via the POST:
URLEncodedPostData encPostData = new URLEncodedPostData("UTF-8", false);
encPostData.append("username", username);
encPostData.append("password", password);
encPostData.append("age", age);
byte[] postData = encPostData.toString().getBytes("UTF-8");
3). Set content-length for the connection (this step may be optional - try without this first, probably the BB OS is smart enough to set this automatically):
httpConn.setRequestProperty("Content-Length", String.valueOf(postData.length));
4). Open an OutputStream and write the content to it (the code is simplified):
OutputStream os = httpConn.openOutputStream();
os.write(postData);
os.flush();
...
httpConn = (HttpConnection)connDesc.getConnection();
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("username",name);
httpConn.setRequestProperty("password",pass);
....

Categories