I am using Apache Commons HttpClient v3.1. All my requests are having correct (default) HTTP version in the request line i.e HTTP/1.1 except for 1 request.
Following Post request gets the requestline as HTTP/0.9:
server : port/cas/v1/tickets/TGT-1-sUqenNbqUzvkGSWW25lcbaJc0OEcJ6wg5DOj3XDMSwoIBf6s7i-cas-1
Body: service=*
I debugged through the http client code and saw the requestline is set to HTTP/1.1 but on the server I see the request coming as HTTP/0.9.
I tried to set the HTTP version explicitly using the HttpMethodParams but that does not help.
Does anyone have an idea what could be wrong?
HttpClient client = new HttpClient();
HostConfiguration hc = client.getHostConfiguration();
hc.setHost(new URI(url, false));
PostMethod method = new PostMethod();
method.setURI(new URI(url, false));
method.getParams().setUriCharset("UTF-8");
method.getParams().setHttpElementCharset("UTF-8");
method.getParams().setContentCharset("UTF-8");
method.getParams().setVersion(HttpVersion.HTTP_1_1);
method.addParameter("service", URLEncoder.encode(service, "UTF-8"));
method.setPath(contextPath + "/tickets/" + tgt);
String respBody = null;
int statusCode = client.executeMethod(method);
respBody = method.getResponseBodyAsString();
Thanks Joachim Sauer. I was able to figure out the problem.
I was using Webscarab as web proxy and it emitted out following message "Got a continuation header but had no previous header line". Looked it up online and found that the problem was in multi-line requestline. I was setting the HTTP version to 1.1 explicitly however there was a trailing '\r\n' in the url which made the requestline look like Http/0.9.
Difference between Http/0.9 and Http/1.0 or other higher protocols is that 0.9 had a simple requestline 'METHOD URL'. Later versions also include the Http version in the request line 'METHOD URL HTTPVERSION'.
Hope it saves someone day!
Related
I am trying to use a web API in a Java program using Apache HttpClient5.
Using a simple request with curl:
curl -X POST -H "x-api-user: d904bd62-da08-416b-a816-ba797c9ee265" -H "x-api-key: xxxxxxxxxxx" https://habitica.com/api/v3/user/class/cast/valorousPresence
I get the expected response and effect.
Using my Java code:
URI uri = new URIBuilder()
.setScheme("https")
.setHost("habitica.com")
.setPath("/api/v3/user/class/cast/valorousPresence")
.build();
Logger logger = LoggerFactory.getLogger(MyClass.class);
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader(new BasicHeader("x-api-user",getApiUser()));
httpPost.addHeader(new BasicHeader("x-api-key", getApiKey()));
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
logger.info(httpResponse.toString());
return httpResponse.getCode();
The output I get when running the Java call is
411 Length Required HTTP/1.0
I'm sure I'm not constructing the POST call correctly, how should it be done? I've tried specifying Content-Type and that has no effect. Trying to set Content-Length in the code causes compilation errors (as I understand it, this is handled behind the scenes by HttpClient5).
All my GET requests using HttpClient5 work fine.
A POST always has a payload (content). A POST without content is unusual, so are you sure you didn't forget something?
You need to call setEntity() to set the payload, even if it is empty, because it is the entity that sets the Content-Length header.
E.g. you could call httpPost.setEntity(new StringEntity("")), which sets Content-Type: text/plain and Content-Length: 0.
POST request to server using java URLConnnection
I need to send a POST request with the two parameters below:
param1=value1
param2=value2
And also I need to send a file.
In the case of Apache these 2 two(sending params and file) things are handled like below
post.setQueryString(queryString) // queryString is url encoded for eg: param1=value1¶m2=value2
post.setRequestEntity(entity) // entity is constructed using file input stream with corresponding format
Please let me know if you have anything related to this problem.
Please note: When I try using Google Chrome REST client plug-in, I am getting the response as below (tried with all request content-types)
UNSUPPORTED FILE FORMAT: 'multipart/form-data' is not a supported content-type
Response code is 400.
Try this API from Apache to send request internally with POST method.
The below is the sample Code to use API
List<org.apache.http.NameValuePair> list =new ArrayList<org.apache.http.NameValuePair>();
HttpPost postMethod = new HttpPost("http://yoururl/ProjectName");
list.add(new BasicNameValuePair("param1", "param1 Value")) ;
postMethod.setEntity(new UrlEncodedFormEntity(list));
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(postMethod);
InputStream is = response.getEntity().getContent();
I am using Apache HTTP Client Library to send HTTP request. I have following questions:
1- Does this library attaches any default headers to the request, or you have to attach all the headers yourself.
HttpClient client = new HttpClient();;
HttGet request = new HttpGet('http://www.example.com');
//Now Can i execute the request directly or do i need to
//add headers before executing the request
client.execute(request);
2- I also want to see the headers that are being sent to the server. I tried "request.getHeaders()" but it just prints - "[Lorg.apache.http.Header;#1bc2616". How can I get it to print headers in a name - value format.
What version of Apache HttpClient are you using? In version 4.0.1 there is a method HttpGet#getAllHeaders() which returns an array of Header object. See grep code here - http://grepcode.com/file/repo1.maven.org/maven2/org.apache.httpcomponents/httpcore/4.0.1/org/apache/http/message/AbstractHttpMessage.java#AbstractHttpMessage.getAllHeaders%28%29
I tried running this code:
final HttpClient client = new DefaultHttpClient();
final HttpGet get = new HttpGet("http://www.google.com");
client.execute(get);
for (final Header header : get.getAllHeaders()) {
System.out.println("Header: " + header.getName() + " = " + header.getValue());
}
System.out.println(get.getAllHeaders().length);
I did not see any headers getting printed in the console and get.getAllHeaders().length returned zero (0). So I would assume that HttpClient doesn't provide any default Headers.
I wouldn't recommend to use separate HttpGet/HttpPost/HttpPut
but HttpRequest Interface. There you'll be able to set Header/body as HttpEntity.
But Default header is attached:
method: GET/POST/PUT by default;
You should separately set Content-Type and Encoding
I'm attempting to query a REST api using POST requests in a java application. I think I've set everything correctly, but I keep getting a Bad Request response.
HttpPost request = new HttpPost(requestURI);
request.addHeader("accept", "application/json");
request.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
HttpEntity entity = new StringEntity(requestBody + new Integer(PatientId).toString() + "}");
request.setEntity(entity);
The requestBody, accompanied by the number and curly brace, are valid JSON, and the requestURI is copy and pasted straight out of the API documentation, so I know I shouldn't be getting a Bad Request due to those.
Am I missing something in the setup?
The Content-Length header is missing. Some servers don't report the correct 4xx error (411 Length Required) and just issue a generic Bad Request error.
It ended up being a random slash that wasn't included in my URI.
I'm trying to send a simple string as the contents of a HttpPost message.
The problem is, the body of the HttpPost message never makes it to the wire. (Says the Wireshark capture). The header looks just fine though (including the correctly calculated Content-Length.
Here's what the code looks like:
String url = "http://1.2.3.4/resource";
HttpClient client = new DefaultHttpClient();
String cmd = "AT+AVLPOS\r\n";
StringEntity se = new StringEntity(cmd);
se.setContentType("text/plain");
HttpPost request = new HttpPost(url);
request.setHeader("Content-Type","text/plain");
request.setEntity(se);
HttpResponse response = client.execute(request);
[...]
The string should be ASCII-encoded, but that's a detail at this point.
This is what shows up in WireShark:
-> note that lines marked with + are what's sent, and - is what's received.
+POST /resource HTTP/1.1
+Content-Type: text/plain
+Content-Length: 11
+Host: 1.2.3.4
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
+Expect: 100-Continue
-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked
-4
-OK
This is what should show up (wrote a very simple console app in C# to do this, it just works):
+POST /resource HTTP/1.1
+Content-Type: text/plain
+Host: 1.2.3.4
+Content-Length: 11
+Expect: 100-continue
+Connection: Keep-Alive
+
-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked
-
+AT+AVLPOS
+
-4
-OK
-
-48
-$AVTMR,99999999,204810,A,1234.2218,N,0123.1051,E,0,20,150811,0,REQ*69
-
-0
-
Any suggestions?
I've figured it out, AND I've learned something today.
Long story short: disable the HttpClient's HTTP Post expect-continue handshake, by setting one of its parameters, this will send the whole request message in one chunk.
//set up HttpPost request as before
HttpClient client = new DefaultHttpClient();
client.getParams().setBooleanParameter("http.protocol.expect-continue", false);
HttpResponse response = client.execute(request);
[...]
Now here's how I got there, maybe this will help someone someday.
First I derived from a HttpEntityWrapper and used that as my request entity to see what gets called when, and found out that the Entity's writeTo(OutputStream) method was never called at all.
Then I started to look at why, in the case of the "correct" behaviour, the POST request wasn't sent all at once, and instead, the request headers were sent, then the response header is received, THEN the request body is sent.
IT's all got to do with the HTTP Post expect-continue handshake. Read more about it on Haacked.
If the expect-continue header is sent in a request, the Http server SHOULD reply with a 100 Continue message signifying "OK, I will accept your message", or with an error, stopping the possibly long POST message in its tracks.
Unfortunately, the web server I run against is a bare bones implementation that runs on a chip, and it sends the wrong reply (200 OK instead of 100 Continue).
The default implementation of the .NET Http Client seems to be more forgiving here: it treats the 200 message as 100 Continue, shrugs, and gets on its way to send the request body.
Not so with the Http client implementation of Android (API level 7).
Next thing I tried was to disable the expect-continue handshake completely, in order to make the HttpClient send the whole request. To my surprise and joy, this was handled fine by the web server, which replied with the information I wanted. Yay!