HTTP POST request in java - setting content length - java

Below is my code which does POST request to login to a website. When i run the same I receive Message response as 411. Can anybody help me to set the correct Content Length?
try {
String request = "http://<domain.com>/login";
URL url = new URL(request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestProperty("Content-Length", "1");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("email", "abc");
connection.setRequestProperty("password", "xyz");
connection.setDoOutput(true);
connection.setRequestMethod("POST");
int code = connection.getResponseCode();
System.out.println("Response Code of the object is " +code);
if(code == 200)
System.out.println("OK");
connection.disconnect();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Ok - you're not moving anything into the body of the request so you should set the length to "0".
Add:
connection.connect();
after:
connection.setRequestMethod("POST");
google "httpurlconnection post parameters" for adding parameters to a POST request. This site has at least four or five solutions.

Although the answer might be too late, but just for future reference.
I faced exactly the same problem and for the reasons already mentioned I kept getting the same error.
I managed to work around the problem by sending just an empty body:
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
byte[] input = "".getBytes("utf-8");
os.write(input, 0, input.length);
}
That fixed the issue for me. Manually setting the Content-Length header does not help as already mentioned.

I was facing the same problem. I was trying to send a POST request with an empty body, but the request was rejected by the server, returning 411.
Then I found the following code in 'sun.net.www.protocol.http.HttpURLConnection', which is the implementation of 'java.net.HttpURLConnection':
private static final String[] restrictedHeaders = new String[]{"Access-Control-Request-Headers", "Access-Control-Request-Method", "Connection", "Content-Length", "Content-Transfer-Encoding", "Host", "Keep-Alive", "Origin", "Trailer", "Transfer-Encoding", "Upgrade", "Via"};
So, when you set a header via sun.net.www.protocol.http.HttpURLConnection.setRequestProperty, if the key is included in the array above, it will be ignored. That's why setting 'Content-Length' manually is not working.

Related

I am confused about something in python to send an HTTP request that I am trying to recreate in java

My friend recently sent me this code:
requests.post("example.com", headers = {'authorization': token}, json = {'content' : message})
it is in python. It is meant to send an HTTP post request to example.com and I am trying to convert it to java.
So far, I have this:
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
//url is defined farther up in the code.
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", token);
However, in my friends code he had 2 different parts that were headers={} and json={}
I don't know how I would do this in java. I am confused what the difference between headers and json is. How would I choose the content of the message? please let me know.
So from what I understand you having issues adding the json content to the request?
setRequestProperty() in java is the same in python as doing the following:
headers = {}
headers['Content-Type'] = "application/json"
headers['Authorization'] = token
I haven't written in Java for a long time but from what I have read you need to do the following:
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; utf-8");
connection.setRequestProperty("Authorization", token);
connection.setDoOutput(true);
// This part sends the json data to the output stream with the headers defined above sent with the data
String inputString = "{variable1: "myvariable1", variable2; "myvariable2"}";
try(OutputStream stream = con.getOutputStream()){
byte[] input = inputString.getBytes("utf-8");
stream.write(input, 0, input.length);
}
You are already setting the headers via "setRequestProperty()" you just need to send the data as well.

Java doesn't send HTTP POST Request

I'm implementing some simple java class in order to send an HTTP Request with POST method and also another java class in order to receive it.
The server works fine when I make a POST request by means of my browser(Chrome), or an application(I have used Postman in this case) but it ends up with problem when I send HTTP Request with java!
My sending HTTP class is "Sender.java", containing the following snippet:
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
os.close();
//connect to the Server(resides at Server.java)
con.connect();
I have commented some lines of code setting Headers like "Accept-Language" and "Content-Type" because I don't know whether or not are these headers required for the java program to work out?
The server is another java program named "Server.java". Here is the snippet related to reading HTTP Request made by the Sender.java(if need be).
int servPort = 8082;
// Create a server socket to accept HTTP client connection requests
HttpServer server = HttpServer.create(new InetSocketAddress(servPort), 0);
System.out.println("server started at " + servPort);
server.createContext("/", new PostHandler());//PostHandler implements HttpHandler
server.setExecutor(null);
server.start();
All I want is to send a plaintext as the body of my HTTP Request with the Post method. I have read plenty of sites and even related questions at this site. But it still doesn't work out. In other words, whenever I create an HTTP Request from "Sender.java", nothing appears at "Server.java". I just want to know what's wrong with my snippets and how should I fix that?
I tested this and it's working:
//Sender.java
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
int httpResult = con.getResponseCode();
con.disconnect();
As you can see, connect is not necessary. The key line is
int httpResult = con.getResponseCode();
When you send a POST form using the browser, it sends the form in a certain format, defined in RFC1866, you have to recreate this on Java when making a post request.
With this format, its important you set the Content-Type header to application/x-www-form-urlencoded, and pass the body as you would do in a url with a get request.
Borrowing some code of my previous answer to POST in Java:
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
Map<String,String> form = new HashMap<>();
// Define the fields
form.put("username", "root");
form.put("password", "sjh76HSn!"); // This is a fake password obviously
// Build the body
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
// Prepare our `con` object
con.setFixedLengthStreamingMode(length);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.connect();
try (OutputStream os = con.getOutputStream()) {
os.write(out);
}
Maybe “localhost” in the sender url does not resolve to the same ip that the server binds to? Try changing to 127.0.0.1 or your actual IP address.
try with PrintStream
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
java.io.PrintStream printStream = new java.io.PrintStream(os);
printStream.println("Just Some Text");
con.getInputStream();//Send request
os.flush();
os.close();

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;
}

Java HTTPUrlConnection returns 500 status code

I'm trying to GET a url using HTTPUrlConnection, however I'm always getting a 500 code, but when I try to access that same url from the browser or using curl, it works fine!
This is the code
try{
URL url = new URL("theurl");
HttpURLConnection httpcon = (HttpURLConnection) url.openConnection();
httpcon.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
httpcon.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:14.0) Gecko/20100101 Firefox/14.0.1");
System.out.println(httpcon.getHeaderFields());
}catch (Exception e) {
System.out.println("exception "+e);
}
When I print the headerfields, it shows the 500 code.. when I change the URL to something else like google.com , it works fine. But I don't understand why it doesn't work here but it works fine on the browser and with curl.
Any help would be highly appreciated..
Thank you,
This is mostly happening because of encoding.
If you are using browser OK, but getting 500 ( internal server error ) in your program,it is because the browsers have a highly sophisticated code regarding charsets and content-types.
Here is my code and it works in the case of ISO8859_1 as charset and english language.
public void sendPost(String Url, String params) throws Exception {
String url=Url;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestProperty("Acceptcharset", "en-us");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestProperty("charset", "EN-US");
con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
String urlParameters=params;
// Send post request
con.setDoOutput(true);
con.setDoInput(true);
con.connect();
//con.
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
this.response=response.toString();
con.disconnect();
}
and in the main program , call it like this:
myclassname.sendPost("https://change.this2webaddress.desphilboy.com/websitealias/orwebpath/someaction","paramname="+URLEncoder.encode(urlparam,"ISO8859_1"))
The status code 500 suggests that the code at web server have been crashed .Use HttpURLConnection#getErrorStream() to get more idea of the error. Refer Http Status Code 500
I ran into the problem of "URL works in browser, but when I do http-get in java I get a 500 Error".
In my case the problem was that the regular http-get ended up in an infinite redirect loop between /default.aspx and /login.aspx
URL oUrl = new URL(url);
HttpURLConnection con = (HttpURLConnection) oUrl.openConnection();
con.setRequestMethod("GET");
...
int responseCode = con.getResponseCode();
What was happening was: The server serves up a three-part cookie and con.getResponseCode() only used one of the parts. The cookie data in the header looked like this:
header.key = null
value = HTTP/1.1 302 Found
...
header.key = Location
value = /default.aspx
header.key = Set-Cookie
value = WebCom-lbal=qxmgueUmKZvx8zjxPftC/bHT/g/rUrJXyOoX3YKnYJxEHwILnR13ojZmkkocFI7ZzU0aX9pVtJ93yNg=; path=/
value = USE_RESPONSIVE_GUI=1; expires=Wed, 17-Apr-2115 18:22:11 GMT; path=/
value = ASP.NET_SessionId=bf0bxkfawdwfr10ipmvviq3d; path=/; HttpOnly
...
So the server when receiving only a third of the needed data got confused: You're logged in! No wait, you have to login. No, you're logged in, ...
To work around the infinite redirect-loop I had to manually look for re-directs and manually parse through the header for "Set-cookie" entries.
con = (HttpURLConnection) oUrl.openConnection();
con.setRequestMethod("GET");
...
log.debug("Disable auto-redirect. We have to look at each redirect manually");
con.setInstanceFollowRedirects(false);
....
int responseCode = con.getResponseCode();
With this code the parsing of the cookie, if we get a redirect in the responseCode:
private String getNewCookiesIfAny(String origCookies, HttpURLConnection con) {
String result = null;
String key;
Set<Map.Entry<String, List<String>>> allHeaders = con.getHeaderFields().entrySet();
for (Map.Entry<String, List<String>> header : allHeaders) {
key = header.getKey();
if (key != null && key.equalsIgnoreCase(HttpHeaders.SET_COOKIE)) {
// get the cookie if need, for login
List<String> values = header.getValue();
for (String value : values) {
if (result == null || result.isEmpty()) {
result = value;
} else {
result = result + "; " + value;
}
}
}
}
if (result == null) {
log.debug("Reuse the original cookie");
result = origCookies;
}
return result;
}
Make sure that your connection allows following redirects - this is one of the possible reasons for difference in behaviour between your connection and the browser (allows redirect by default).
It should be returning code 3xx, but there maybe something else somewhere that changes it to 500 for your connection.
I faced the same issue, and our issue was there was a special symbol in one of the parameter values. We fixed it by using URLEncoder.encode(String, String)
In my case it turned out that the server always returns HTTP/1.1 500 (in Browser as in Java) for the page I wanted to access, but successfully delivers the webpage content nonetheless.
A human accessing the specific page via Browser just doesn't notice, since he will see the page and no error message, in Java I had to read the error stream instead of the input stream (thanks #Muse).
I have no idea why, though. Might be some obscure way to keep Crawlers out.
This is an old question, but I have had same issue and solved it this way.
This might help other is same situation.
In my case I was developing system on local environment, and every thing worked fine when I checked my Rest Api from browser but I got all the time thrown HTTP error 500 in my Android system.
The problem is when you work on Android, it works on VM (Virtual Machine), that said it means your local computer firewall might preventing your Virtual Machine accessing the local URL (IP) address.
You need just to allow that in your computer firewall. The same thing apply if you trying to access system from out side your network.
Check the parameter
httpURLConnection.setDoOutput(false);
Only for GET Method and set to true on POST, this save me lot of time!!!

HttpURLConnection sends a POST request even though httpCon.setRequestMethod("GET"); is set

Here is my code:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setDoInput(true);
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.setRequestMethod("GET");
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
httpCon.connect();
OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream());
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
out.close();
What I see in response:
500 Server error
I open my httpCon var, and what I see:
POST /rest/platform/domain/list HTTP/1.1
Why is it set to POST even though I have used httpCon.setRequestMethod("GET"); to set it to GET?
The httpCon.setDoOutput(true); implicitly set the request method to POST because that's the default method whenever you want to send a request body.
If you want to use GET, remove that line and remove the OutputStreamWriter out = new OutputStreamWriter(httpCon.getOutputStream()); line. You don't need to send a request body for GET requests.
The following should do for a simple GET request:
String addr = "http://172.26.41.18:8080/domain/list";
URL url = new URL(addr);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setUseCaches(false);
httpCon.setAllowUserInteraction(false);
httpCon.addRequestProperty("Authorization", "Basic YWRtaW4fYFgjkl5463");
System.out.println(httpCon.getResponseCode());
System.out.println(httpCon.getResponseMessage());
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Unrelated to the concrete problem, the password part of your Authorization header value doesn't seem to be properly Base64-encoded. Perhaps it's scrambled because it was examplary, but even if it wasn't I'd fix your Base64 encoding approach.

Categories