Java Applet 411 Content Length - java

I am new to Java. I wrote an applet with a gui that sends results (int w and int p) to a server, and I get the "411 Length Required" error. What am I doing wrong? How do you set a Content-Length?
This is the method that communicates with the server:
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
String charset = "UTF-8";
String query = String.format("?key=%s&value=%s",
URLEncoder.encode(String.valueOf(w), charset),
URLEncoder.encode(String.valueOf(p), charset));
String length = String.valueOf((url + query).getBytes("UTF-8").length);
HttpURLConnection connection = (HttpURLConnection) new URL(url + query).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", length);
connection.connect();
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}

I'm not 100% sure why you're getting a 411 error code, but it probably has to do with the fact that you are not sending any content with your POST. The content-length header should be the length in bytes of the body of the request. You are setting it to the length of the url!
Either change the request to a GET or put the query into the body of the request instead of into the url itself. If you do the latter, set the content-length to the length of the body only.
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
String charset = "UTF-8";
String query = String.format("key=%s&value=%s",
URLEncoder.encode(String.valueOf(w), charset),
URLEncoder.encode(String.valueOf(p), charset));
byte[] queryBytes = query.getBytes("UTF-8");
String length = String.valueOf((url + query).getBytes("UTF-8").length);
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", length);
OutputStream os = connection.getOutputStream();
os.write(queryBytes);
os.flush();
connection.connect();
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}

Request uri includes query , can use GET method.
connection.setRequestMethod("POST"); // modify to GET
connection.setRequestProperty("Content-Length", length); //remove the line
if use POST method, include 'content-length' heade, must send data.
for example:
public void sendPoints1(int w, int p){
try {
String url = "http://somename.com:309/api/Results";
//value type is int ,don't need URLEncoder.
byte[] data = ("key="+w+"&value="+p).getBytes("UTF-8");
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", data.length);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //URLencode...
OuptputStream out = connection.getOutputStream();
out.write(data);
out.flush();
InputStream in = connnection.getInputStream();
//read .....
System.out.println("Responce Code: " + connection.getResponseCode());
System.out.println("Responce Message: " + connection.getResponseMessage());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}

Since all information is passed as query string which is a part of URL, you need not setRequestMethod as POST. But if you still want to set it to POST as part of your logic, then setRequestProperty("Content-Length", "0") as Http Server expect Length to be read when POST method is called. In your case nothing is written as POST information so better set it to ZERO, even thought default value is ZERO at times server may give response errorCode as 411, response Message: Required Length

Related

How can Upload a file to Sharepoint?

private void uploadDocToSharePoint(String token, Resource resource, String folderName) {
try {
String uploadUrl = Utils.SHARE_POINT_DOMAIN + "_api/web/getfolderbyserverrelativeurl('" + folderName + "')/files/add(url='" + resource.getFilename() + "', overwrite=true)";
URL url = new URL(uploadUrl);
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
// Set Header
httpConn.setDoOutput(true);
httpConn.setDoOutput(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("Authorization", "Bearer " + token);
httpConn.setRequestProperty("accept", "application/json; odata=verbose");
httpConn.setRequestProperty("Content-Type", "application/xml");
OutputStream os = httpConn.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
osw.write("Just Some Text");
osw.flush();
osw.close();
os.close(); //don't forget to close the OutputStream
httpConn.connect();
System.out.println(httpConn.getResponseCode());
System.out.println(httpConn.getResponseMessage());
String result;
BufferedInputStream bis = new BufferedInputStream(httpConn.getInputStream());
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result2 = bis.read();
while(result2 != -1) {
buf.write((byte) result2);
result2 = bis.read();
}
result = buf.toString();
System.out.println(result);
} catch (Exception e) {
System.out.println("Error while reading file: " + e.getMessage());
}
}
httpConn.getResponseCode() is 400 and httpConn.getResponseMessage() is Bad Request.
I have tested this request with the URL generated in this class on Postman.
it works correctly.
so I am sure about url and token is correct.
It creates an Empty file successfully.
But as I mentioned the response status is 400 and Bad Request.
I am not sure what is wrong with the following class
Sharepoint guide here
My class copied from here
screenshot here
Pls follow Sharepoint guide here

How to stop a string from being cut off in Java

I have a java code to call a REST API which returns a JWT token as a response. I send a GET call to the API and it will return a JWT token as a response. The token is being returned fine. However, I've noticed somehow the token is being trimmed.
I tried everything online and nothing seems to be working for me. Below is my code :
try {
URL url = new URL(proxyService.getProperty("proxy.url") + "/" + sessionToken);
log.logText("Connection URL: " + url, logLevel);
String readLine = null;
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream in = ((URLConnection)conn).getInputStream();
int length = 0;
StringBuffer response = new StringBuffer();
byte[] data1 = new byte[1024];
while (-1 != (length = in.read(data1))) {
response.append(new String(data1, 0, length));
}
log.logText("JSON String Result: " + response.toString(), logLevel);
}
conn.disconnect();
} catch(MalformedURLException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
oauthToken = oauthToken.replaceAll("^\"|\"$", "");
log.logText("OAuth2 Token: " + oauthToken, logLevel);
return oauthToken;
Regards,
Learnmore
As #markspace mentioned, please specify the data type for oauthToken (I believe it is of type String). Print the total String and then the length before replaceALL and after replaceALL. compare whats replace adds to the total length if yes then there is no issue of string getting trimmed.
You are not assigning response value to anything. I assume you should be assigning it to oauthToken variable.
Also please close the InputStream instance in finally clause, otherwise you will cause resource leakage.
I think you have to close InputStream first, to flush internal buffer.
public static String getOauthToken() throws IOException {
URL url = new URL(proxyService.getProperty("proxy.url") + "/" + sessionToken);
log.logText("Connection URL: " + url, logLevel);
String oauthToken = readInputString(url);
oauthToken = oauthToken.replaceAll("^\"|\"$", "");
log.logText("OAuth2 Token: " + oauthToken, logLevel);
return oauthToken;
}
private static String readInputString(URL url) throws IOException {
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)
throw new RuntimeException("Not expected response code");
try (InputStream in = conn.getInputStream()) {
StringBuffer buf = new StringBuffer();
byte[] b = new byte[1024];
while (true) {
int readBytes = in.read(b);
if (readBytes == -1)
break;
buf.append(new String(b, 0, readBytes));
}
log.logText("JSON String Result: " + buf, logLevel);
return buf.toString();
}
}
It looks like the actual application that I'm calling from is cutting off the response value. I shortened the length of the JWT token and it's not cutting it off. The application must have a limit for a maximum number of characters allowed in a string could be for performance reasons.

EDIT: How do I send this post Request with parameters AND form-data like this postman screenshot in JAVA?

I'm trying to send a POST request to grab comments but it doesn't work in Java while it does work with postman.
I get an 403 Forbidden error, but on postman it retrieves the data i need just fine..
Here's the Java code I'm trying to use to replicate the behavior.
String targetUrl = YOUTBE_COMMENTS_AJAX_URL;
String urlParameters = "action_load_comments=1&order_by_time=True&filter=jBjXVrS8nXs";
String updatedURL = targetUrl + "?" + urlParameters;
URL url = null;
InputStream stream = null;
HttpURLConnection urlConnection = null;
try {
url = new URL(updatedURL);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("content-type", "multipart/form-data");
urlConnection.setRequestProperty("user-agent", "USER_AGENT");
urlConnection.setDoOutput(true);
String data = URLEncoder.encode("video_id", "UTF-8")
+ "=" + URLEncoder.encode(youtubeId, "UTF-8");
data += "&" + URLEncoder.encode("session_token", "UTF-8") + "="
+ URLEncoder.encode(xsrfToken, "UTF-8");
data += "&" + URLEncoder.encode("page_token", "UTF-8") + "="
+ URLEncoder.encode(pageToken, "UTF-8");
urlConnection.connect();
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
wr.write(data);
wr.flush();
stream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"), 8);
String result = reader.readLine();
return result;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
Here's an example of what postman is sending in their headers
It seems like your problem is here (see inline comments):
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(urlParameters);
// you wrote your URL parameters into Body
wr.flush();
wr.close();
//You closed your body and told server - you are done with request
conn.getOutputStream().write(postDataBytes);
// you wrote data into closed stream - server does not care about it anymore.
You have to append your urlParameters directly to the URL when you open it
Then you have to write your Form Data into body as you do:
conn.getOutputStream().write(postDataBytes);
and then close output stream

Google Drive REST API Resumable upload returnin 400 Bad Request

I am trying to uploading chunks of 256 KB in Google Drive using REST API v3. I can successfully get the upload ID but when I use this upload ID to upload a chunk, I get a 400 Bad Request instead of 308. I am posting the code below. The method getUploadID() initiates a resumable upload session and the method putFileWithUploadID() should upload a chunk of the file but there seems to be a problem in it. I have written the code according to the official guide.
String mUploadID;
private String getUploadID(Uri fileUri, String token) {
String upload_id = "";
java.io.File fileContent = new java.io.File(fileUri.getPath());
String fileName = fileContent.getName();
String mimeType = "audio/mpeg";
try {
String url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Authorization", "Bearer " + token);
con.setRequestProperty("X-Upload-Content-Type", mimeType);
con.setRequestProperty("X-Upload-Content-Length", String.format(Locale.ENGLISH, "%d", fileContent.length()));
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
String body = "{\"name\": \"" + fileName + "\", \"parents\": [\"" + "0B7ypsm4HGZhCS3FXcldPZnFPNkE" + "\"]}";
con.setRequestProperty("Content-Length", String.format(Locale.ENGLISH, "%d", body.getBytes().length));
OutputStream outputStream = con.getOutputStream();
outputStream.write(body.getBytes());
outputStream.close();
con.connect();
String location = con.getHeaderField("Location");
if (location.contains("upload_id")) {
String[] uploadParameters = location.split("upload_id");
upload_id = uploadParameters[1].replace("=", "");
}
} catch (Exception e) {
e.printStackTrace();
}
return upload_id;
}
private void putFileWithUploadID(Uri fileUri, String token, long range) {
java.io.File fileContent = new java.io.File(fileUri.getPath());
String fileName = fileContent.getName();
String contentLength = String.valueOf(fileContent.length());
String mimeType = "audio/mpeg";
long totalBytesFromDataInputStream = 0;
long uploadedBytes = 0;
long chunkStart = 0;
long chunkSize = 262144;
do {
try {
String url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" + mUploadID;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("PUT");
con.setDoOutput(true);
con.setConnectTimeout(10000);
con.setRequestProperty("Content-Type", mimeType);
uploadedBytes = chunkSize;
if (chunkStart + uploadedBytes > fileContent.length()) {
uploadedBytes = (int) fileContent.length() - chunkStart;
}
con.setRequestProperty("Content-Length", String.format(Locale.ENGLISH, "%d", uploadedBytes));
con.setRequestProperty("Content-Range", "bytes " + chunkStart + "-" + (chunkStart + uploadedBytes - 1) + "/" + fileContent.length());
byte[] buffer = new byte[(int) uploadedBytes];
FileInputStream fileInputStream = new FileInputStream(fileContent);
fileInputStream.getChannel().position(chunkStart);
if (fileInputStream.read(buffer, 0, (int) uploadedBytes) == -1) {
break;
}
fileInputStream.close();
OutputStream outputStream = con.getOutputStream();
outputStream.write(buffer);
outputStream.close();
con.connect();
int responseCode = con.getResponseCode();
String rangeHeader = con.getHeaderField("Range");
if (rangeHeader!=null) {
chunkStart = Long.parseLong(rangeHeader.substring(rangeHeader.lastIndexOf("-") + 1, rangeHeader.length())) + 1;
}
} catch (Exception e) {
e.printStackTrace();
}
} while ((chunkStart+chunkSize)<fileContent.length());
}
Basically, 400: Bad Request means that a required field or parameter has not been provided, the value supplied is invalid, or the combination of provided fields is invalid.
This error can be thrown when trying to add a duplicate parent to a Drive item. It can also be thrown when trying to add a parent that would create a cycle in the directory graph.
You may also check this related SO post which suggested to properly use the Android-specific API to do resumable upload. See creating files.

Java HTTP post assistance

I've been working with the Slack API in java and have been trying to get an HTTP method that can be used like my below example block of code. That code block works, but the issue is I need to also include a 200 response code, and can't figure out how to get it to work.
Basically, how can I, In Java, send an HTTP post and also tag on the 200 status code using the URL and the content?
Current code:
public void httpRequest(URL url, String content) {
try {
byte[] contentBytes = content.getBytes("UTF-8");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length", Integer.toString(contentBytes.length));
connection.setRequestProperty("Status", Integer.toString(200));
OutputStream requestStream = connection.getOutputStream();
requestStream.write(contentBytes, 0, contentBytes.length);
requestStream.close();
String response = "";
BufferedReader responseStream;
response = "" + ((HttpURLConnection) connection).getResponseCode();
try {
if (((HttpURLConnection) connection).getResponseCode() == 200) {
responseStream = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
} else {
responseStream = new BufferedReader(new InputStreamReader(((HttpURLConnection) connection).getErrorStream(), "UTF-8"));
}
response = responseStream.readLine();
responseStream.close();
} catch (NullPointerException ignored) {
}
} catch (IOException e) {
e.printStackTrace();
}
}
The call to setDoOutput(true) triggers a post, i.e. you do not need to add
connection.setRequestMethod("POST");
Adding a status header to the request is possible, as you have done, but typically one associates status codes with http responses, not requests. - And off course, adding such custom header would only make sense if the server was designed to use this information to anything.
See this big, and highly up-voted answer on java.net.HttpURLConnection.
Also, you have some problems relating to your response variable as well as the BufferedReader. You accidentally override the value you initially assigned to the response field, instead of concatening. Also, your readLine() should probably be in a loop:
String tmp;
while ((tmp = responseStream.readLine()) !=null){
response += tmp;
}

Categories