I'm using org.apache.http.client.HttpClient and I'm trying to access the payload of the request HTTPEntity without consuming the underlying stream.
I tried using
EntityUtils.toString(someEntity);
but this consumes the stream.
I just want to preserve the payload which was sent in a HTTP request to a String object for e.g.
Sample Code:
String uri = "someURI";
HttpPut updateRequest = new HttpPut(uri);
updateRequest.setEntity(myHttpEntity);
Any hint appreciated.
A HttpEntity must be repeatable for it to be repeatedly consumable. The method isRepeatable() shows whether or not this is the case.
Two entities are repeatable:
StringEntity
ByteArrayEntity
This means you have to add one of these to the original request so you can keep using using its content.
public void doExample() {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPut httpPut = new HttpPut("some_url");
httpPut.setHeader(CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
StringEntity jsonEntityOrso = new StringEntity("{ \"hello\": \"some message\" }");
httpPut.setEntity(jsonEntityOrso);
StringEntity reusableEntity = (StringEntity) httpPut.getEntity();
String hello = readInputStream(reusableEntity.getContent());
String hello2 = readInputStream(reusableEntity.getContent());
boolean verify = hello.equals(hello2); // returns true
}
private String readInputStream(InputStream stream) {
return new BufferedReader(
new InputStreamReader(stream, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
}
Related
I have used the CloseableHttpClient APi for a Post call and Basic Auth for authorisation
private CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("https://example.com");
MyJson myJson = new MyJson(); //custom java object to be posted as Request Body
Gson gson = new Gson();
String param = gson.toJson(myJson);
StringEntity urlparam = new StringEntity(param);
String credentials = username + ":" + passwprd;
String base64Credentials = new String(Base64.getencoder().encode(credentials.getBytes()));
String authorizartionHeader = "Basic" + base64Credentials;
httppost.setHeader("Content-Type", "application/Json");
httppost.setHeader("Authorization", authorizartionHeader);
urlparam.setContentEncoding("UTF-8");
httppost.setEntity(urlparam);
httpclient.execute(httppost);
I am getting error
"Invalid UTF-8 middle byte"
I have encoded the JSON still the encoding is not working for other locales except English. How to encode the Post data.
I tried using the method
httppost.setEntity(new URLEncodedFormEntity(namevaluePair, "UTF-8")) but I don't have any Namevaluepair and if the add the Username-pswd in that then getting Null pointer response.
You should try to set everything as UTF-8
StringEntity urlparam = new StringEntity(param, StandardCharsets.UTF_8);
And add proper header
httppost.setHeader("Content-Type", "application/json;charset=UTF-8");
I am trying to do a HTTP post request to a web API and then parse the received HttpResponse and access the key value pairs in the body. My code is like this:
public class access {
// http://localhost:8080/RESTfulExample/json/product/post
public static void main(String[] args) {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("https://XXXXXXX/RSAM_API/api/Logon");
// Request parameters and other properties.
List<NameValuePair> urlParameters = new ArrayList<NameValuePair>(2);
urlParameters.add(new BasicNameValuePair("UserId", "XXXXX"));
urlParameters.add(new BasicNameValuePair("Password", "XXXXXX"));
try {
httppost.setEntity(new UrlEncodedFormEntity(urlParameters));
//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
while(null !=(line=rd.readLine())){
System.out.println(line);
}
System.out.println(response);
String resp = EntityUtils.toString(response.getEntity());
JSONObject obj = new JSONObject(resp);
}
catch (Exception e){
e.printStackTrace();
}
}
}
I am trying to access the body by converting it to a JSONObject with these 2 lines of code:
String resp = EntityUtils.toString(response.getEntity());
JSONObject obj = new JSONObject(resp);
But I get an error in the second line saying:
JSONObject
(java.util.Map)
in JSONObject cannot be applied
to
(java.lang.String)
Not sure if this is the correct approach. Is there a way to do what I am trying to do?
Any help would be appreciated, Thank you.
EDIT:
So when I try to print the response body using the following lines,
String resp = EntityUtils.toString(response.getEntity());
System.out.println(resp);
I get the result: {"APIKey":"xxxxxxxxxxxxxx","StatusCode":0,"StatusMessage":"You have been successfully logged in."}
I am looking for a way to parse this result and then access each element. Is there a way to do this?
According to JsonSimple's JsonObject documentation it takes map in the constructor but not a String. So the error you are getting what it says.
You should use JSONParser to parse the string first.
Its also better to provide the encoding as part of EntityUtils.toString say UTF-8 or 16 based off your scenario.
IOUtils.toString() from Apache Commons IO would be a better choice to use too.
Try the below line to parse the JSON:
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(resp);
The above lines will vaildate the JSON and through exception if the JSON is invalid.
You don't need to read the response in the extra while loop. EntityUtils.toString(response.getEntity()); will do this for you. As you read the response stream before, the stream is already closed when comming to response.getEntity().
I started developing in Xamarin, and then decided that license may be a bit expensive for playing around, so I'm transferring my code to java.
I have a small chunk that performs a POST with a JSON object, and it works in Xamarin and doest work in Java.
Xamarin:
var client = new HttpClient ();
var content = new FormUrlEncodedContent(new Dictionary<string, string>() {
{"action", "getEpisodeJSON"},
{"episode", "11813"}
});
client.DefaultRequestHeaders.Referrer = new Uri(link);
var resp = client.PostAsync("http://www.ts.kg/ajax", content).Result;
var repsStr = resp.Content.ReadAsStringAsync().Result;
dynamic res = JsonConvert.DeserializeObject (repsStr);
Android:
HttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost = new HttpPost("http://www.ts.kg/ajax");
String json = "";
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("action", "getEpisodeJSON");
jsonObject.accumulate("episode", "11813");
// 4. convert JSONObject to JSON to String
json = jsonObject.toString();
// 5. set json to StringEntity
StringEntity se = new StringEntity(json);
// 6. set httpPost Entity
httpPost.setEntity(se);
// 7. Set some headers to inform server about the type of the content
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.addHeader("Referer", "http://www.ts.kg");
// 8. Execute POST request to the given URL
HttpResponse httpResponse = httpclient.execute(httpPost);
// 9. receive response as inputStream
InputStream inputStream = httpResponse.getEntity().getContent();
// 10. convert inputstream to string
String result;
if(inputStream != null)
result = convertInputStreamToString(inputStream);
What is a correct way to make such a POST in Android?
UPD
Current problem is that i'm getting an empty result string;
private static String convertInputStreamToString(InputStream inputStream) throws IOException{
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
return result;
}
I ended up catching all requests of my device via Fiddle (good tutorial is here: http://tech.vg.no/2014/06/04/how-to-monitor-http-traffic-from-your-android-phone-through-fiddler/)
The difference was in cookie, so I used and HttpContex variable as described here:
Android HttpClient Cookie
And I also had a different Content-Type, so I set this header manually as this:
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
I am trying to send a http request to a website which is supposed to return a json response. The problem is that i am not getting the json data. But when i paste the url in a browser it displays the json output. Am a newbie. Kindly help.
Here is my code
HttpClient client = new DefaultHttpClient();
String url="http://directclientvendors.com/news24/api/get.php?type=news";
HttpGet request = new HttpGet(url);
HttpResponse response;
response = client.execute(request);
BufferedReader br =
new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while(br.ready())
{
line+=br.readLine();
}
System.out.println("line "+line);
You should be executing a GET request and not a POST. Please change the request type to HttpGet. The browser executes a GET on the URL when you paste it on the address bar and hit enter.
Additionally use a Reader + StringBuilder / JsonReader / GSON to read from the URL's response content. String concatenation leads to the creation of additional objects unnecessarily.
[EDIT]
To my astonishment the API call works even when a POST call is made to get the resource. The problem must be in your parsing logic. Using a JsonReader works fine for me. This is just template code, but you can fill in the rest to get the other JSON elements. Regardless of whether POST works or not, you should still use GET for this call.
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://directclientvendors.com/news24/api/get.php?type=news");
HttpResponse response = client.execute(request);
InputStream content = response.getEntity().getContent();
JsonReader jsonReader = new JsonReader(new InputStreamReader(content, "UTF-8"));
jsonReader.beginObject();
if(jsonReader.hasNext())
{
System.out.println(jsonReader.nextName()); // prints 'news'
// BEGIN_ARRAY etc to parse the rest
}
// END_OBJECT and cleanup
I have the following code:
HttpGet httpGet = new HttpGet(serverAdress + "/rootservices");
httpGet.setHeader("Accept", "text/xml");
HttpResponse response = client.execute(httpGet, localContext);
String projectURL = XMLDocumentParser.parseDocument(response.getEntity().getContent(), "oslc_scm:scmServiceProviders", "rdf:resource");
String workItemURL = XMLDocumentParser.parseDocument(response.getEntity().getContent(), "oslc_cm:cmServiceProviders", "rdf:resource");
The problem here is that I read two times the HttpResponse object. So the second time I get the exception. But although I know the problem, I can´t find an easy solution. So what is a good way to solve that problem?
Read the input stream returned by response.getEntity().getContent() into a byte[], stored in a local variable. See Convert InputStream to byte array in Java.
byte[] content = IOUtils.toByteArray(response.getEntity().getContent());
String projectURL = XMLDocumentParser.parseDocument(new ByteArrayInputStream(content), "oslc_scm:scmServiceProviders", "rdf:resource");
String workItemURL = XMLDocumentParser.parseDocument(new ByteArrayInputStream(content), "oslc_cm:cmServiceProviders", "rdf:resource");
Read the response content only once, and copy it to some kind of buffer compatible with XMLDocumentParser.parseDocument. Then parse the data directly from your buffer, as many times as you want.
Why don't you try it this way?
HttpGet httpGet = new HttpGet(serverAdress + "/rootservices");
httpGet.setHeader("Accept", "text/xml");
InputStream in = null;
HttpResponse response = client.execute(httpGet, localContext);
in = response.getEntity().getContent();
String projectURL = XMLDocumentParser.parseDocument(in, "oslc_scm:scmServiceProviders", "rdf:resource");
String workItemURL = XMLDocumentParser.parseDocument(in, "oslc_cm:cmServiceProviders", "rdf:resource");