Java equivalent of a python GET request? [duplicate] - java

This question already has answers here:
How to set Cookies at Http Get method using Java
(3 answers)
Closed 3 years ago.
I am trying to perform the same task in Java, but can't seem to figure out how to particularly set the cookies.
I know how to do this in python:
response = requests.get(app_url,cookies=cookies,allow_redirects=False)
How do I do the equivalent in Java?

Open a URLConnection(HttpURLConnection or HttpsURLConnection, set the cookie and connect.
HttpURLConnection con;
InputStream is;
try{
con=((HttpURLConnection)new URL(app_url).openConnection());
con.setRequestProperty("Cookie",cookie);
is=con.openStream();
//recv code
}finally{
if(is!=null){try{is.close();}catch(IOException e){}}
if(con!=null){try{con.close();}catch(IOException e){}
}

The typical solution is using Apache HttpClient. If you need a less engineered and/or third-party library free solution, I'd suggest URLConnection or the new Java 11 HttpClient.
private final CloseableHttpClient client = HttpClients.createDefault();
...
public String get(String appUrl, String cookie) {
HttpGet request = new HttpGet(appUrl);
request.setHeader("Cookie", cookie);
try (CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
}

Using Java11's HttpClient it could look like follows:
HttpResponse<String> response = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NEVER)
.build()
.send(
HttpRequest.newBuilder(URI.create(url))
.header("cookieName", "cookieValue")
.GET()
.build(),
HttpResponse.BodyHandlers.ofString());

I assume you can reliably do the request. If not, this could help you.
How to get HTTP response code for a URL in Java?
To handle cookies, you may want to look at this
How to set Cookies at Http Get method using Java
Both implementations use the basic Java HttpURLConnection class.

Related

Is URL.openStream() the same as respone.getEntity().getContent()?

There is a file that will be downloaded when I make a get request to particular URL. I am able to get InputStream from both ways.
Method 1
Using URL class in java.net package.
java.net.URL url = new URL(downloadFileUrl);
InputStream inputStream = url.openStream();
Method 2
Using Apache's HttpClient class.
org.apache.http.impl.client.CloseableHttpClient httpclient = new CloseableHttpClient();
HttpGet request = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute((HttpUriRequest)request);
InputStream inputStream = response.getEntity().getContent();
Are these methods the same? If not how? Which method is preferred generally or in a specific situation?
The examples I provided are simplistic. Assume I did the neccessary
congifurations with the URL and HttpClient objects to get successful response.
Both methods returns the input stream to read from the connection. There isn't difference between these methods. Since HttpClient is third party library, you need to keep a check for any vulnerabilities and keep updating the library.
Only difference is HttpClient supports only HTTP(s) protocol, whereas URLConnection can be used for other protocols too like FTP
In terms of functionalities, Apache HttpClient has more fine tuning options than URLConnection

Rest api call and POST request (java)

I am pretty new concerning REST api and POST request.
I have the url of a REST api. I need to access to this api by doing an API call in JAVA thanks to a client id and a client secret (I found a way to hash the client secret). However, as I am new I don't know how to do that api call. I did my research during this all day on internet but I found no tutorial, website or anything else about how to do an api call. So please, does anyone know a tutorial or how to do that? (if you also have something about POST request it would be great)
I would be very thankful.
Thank you very much for your kind attention.
Sassir
Here's a basic example snippet using JDK classes only. This might help you understand HTTP-based RESTful services a little better than using a client helper. The order in which you call these methods is crucial. If you have issues, add a comments with your issue and I will help you through it.
URL target = new URL("http://www.google.com");
HttpURLConnectionconn = (HttpURLConnection) target.openConnection();
conn.setRequestMethod("GET");
// used for POST and PUT, usually
// conn.setDoOutput(true);
// OutputStream toWriteTo = conn.getOutputStream();
conn.connect();
int responseCode = conn.getResponseCode();
try
{
InputStream response = conn.getInputStream();
}
catch (IOException e)
{
InputStream error = conn.getErrorStream();
}
You can also use RestTemplate from Spring: https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
Fast and simple solution without any boilerplate code.
Simple example:
RestTemplate rest = new RestTemplate();
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("firstParamater", "parameterValue");
map.add("secondParameter", "differentValue");
rest.postForObject("http://your-rest-api-url", map, String.class);
The Restlet framework also allows you to do such thing thanks to its class ClientResource. In the code below, you build and send a JSON content within the POST request:
ClientResource cr = new ClientResource("http://...");
SONObject jo = new JSONObject();
jo.add("entryOne", "...");
jo.add("entryTow", "...");
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Restlet allows to send any kind of content (JSON, XML, YAML, ...) and can also manage the bean / representation conversion for you using its converter feature (creation of the representation based on a bean - this answer gives you more details: XML & JSON web api : automatic mapping from POJOs?).
You can also note that HTTP provides an header Authorization that allows to provide authentication hints for a request. Several technologies are supported here: basic, oauth, ... This link could help you at this level: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
Using authentication (basic authentication for example) can be done like this:
String username = (...)
String password = (...)
cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, username, password);
(...)
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Hope it helps you,
Thierry

cURL DELETE in Java [duplicate]

This question already has answers here:
How to send PUT, DELETE HTTP request in HttpURLConnection in JAVA
(3 answers)
Closed 8 years ago.
Like the title says, I'm trying to write the following curl DELETE command in Java.
curl -X DELETE -H "Content-Type: application/json; charset=UTF-8" http://10.84.14.2:8082/virtual-network/47a91732-629b-4cbe-9aa5-45ba4d7b0e99
My understanding is that you have to format the DELETE request inside of a POST. Below is my working code for a GET call.
URL dc0ContrailUrl2 = new URL("http://10.10.10.120:8082/network-policy/363bf699-6417-486e-9791-d5aaf873d9bb");
URLConnection dcConn2 = dc0ContrailUrl2.openConnection();
dcConn2.setRequestProperty("Content-Type", "application/json");
BufferedReader in2 = newBufferedReader(newInputStreamReader(dcConn2.getInputStream()));
String inputLine2;
while ((inputLine2 = in2.readLine()) != null){ //while response is not null, assign response to inputLine and print inputLine
System.out.println(inputLine2);
}
in2.close();
When I looked around for how to approach a DELETE request, I ended up with the following:
URL url3 = new URL("http://10.10.10.120:8082/network-policy/363bf699-6417-486e-9791-d5aaf873d9bb");
HttpURLConnection httpConnection3 = (HttpURLConnection) url3.openConnection();
httpConnection3.setDoOutput(true);
httpConnection3.setRequestProperty("Content-Type", "application/json" );
httpConnection3.setRequestMethod("DELETE");
At this point I've gone so far down the google rabbit hole that I'm certain the solution is very simple and is just a matter of changing some syntax/method calls. Any help is greatly appreciated.
Note: I am able to get the DELETE call to work using Postman(chrome app) by simply entering the URL http://10.10.10.120:8082/network-policy/363bf699-6417-486e-9791-d5aaf873d9bb, and switching the drop down menu to DELETE, so I know my URL isn't the issue.
Instead of using HttpURLConnection directly, try with a library like the HttpClient from the Apache HttpComponents, an example of how you can use it with your delete command:
void sendDelete() throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
// create DELETE REQUEST
HttpDelete httpDelete = new HttpDelete(
"http://10.84.14.2:8082/virtual-network/47a91732-629b-4cbe-9aa5-45ba4d7b0e99");
// add header "content-type"
httpDelete.addHeader(new BasicHeader("Content-Type", "application/json; charset=UTF-8"));
// send request
CloseableHttpResponse response1 = httpclient.execute(httpDelete);
// close response (ideally inside a finally clause in a try/catch)
response1.close();
}
My understanding is that you have to format the DELETE request inside of a POST.
That is incorrect. The Curl command you posted performs a 'DELETE' request, and in this sense POST and DELETE (and GET) are alternative HTTP request "methods". There might be web services that accept some kind of delete command in the form of a POST and/or GET request, but that's not what Curl is doing. (It's also not what Postman is doing when you select the 'DELETE' request method.)
Your code is actually pretty much right. It's not useful to specify that you're going to do output (because you're not), nor, therefore, to specify a Content-type (because the request will have no content), but it's probably not harmful to do so. You could even setDoInput(false) on the connection, since you wouldn't normally expect the server to send any content in its response, but leaving that out should be ok, too.
The main thing you're missing is a call to the connection's connect() method. You don't need that in your "GET" example because reading the connection's input stream causes it to connect automatically.

android HTTP POST fail

I'm trying to connect and post to a simple java webservice, running the post's URL from chrome succeeded, but android code skip the following lines (without throwing errors), but the webservice doesn't accept the post
HttpPost post = new HttpPost(setFacebookEventsAddress+userId+"/"+accesstoken);
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
HttpResponse response = client.execute(post);
the webservice method signature handling the above request:
#GET
#Path("setData/{user_id}/{accessToken}")
#Produces(MediaType.APPLICATION_JSON+ ";charset=utf-8")
public String setData(#PathParam("user_id") String user_id,
#PathParam("accessToken") String accessToken) {
since I manage to post throw my browser, anyone can help with what's wrong with my android code?
URL url = new URL(setFacebookEventsAddress+userId+"/"+accesstoken);
HttpURLConnection con = (HttpURLConnection) url
.openConnection();
ja = readStream(con.getInputStream());
Using HttpURLConnection instead of HttpPost did the trick for me, thanks for all the helpers!
It is not possible to say with any certainty (given the evidence), but my guess would be that the expression
setFacebookEventsAddress + userId + "/" + accesstoken
is evaluating to a different URL to the one you are using from the web browser.
I suggest that you try the following:
Turn on request logging on your server, and compare the URLs in the requests being sent.
Modify your client to print out the response status code and the response body. The latter is likely to be an error page that will give you more clues.
Another possible problem is that your code doesn't appear to be sending any body with the POST request.
On revisiting this, the problem was that you were using / trying to do a POST to a web service that you had configured to support GET only. I expect that if you had looked at the status code you would have found that the response code was "Method not supported".

HttpClient - Cookies - and JEditorPane

I've successfully managed to logon to a site using httpclient and print out the cookies that enable that logon.
However, I am now stuck because I wanted to display subsequent pages in a JEditorPane using .setPage(url) function. However, when I do that and analyse my GET request using Wireshark I see that the user agent is not my httpclient but the following:
User-Agent: Java/1.6.0_17
The GET request (which is coded somewhere in side jeditorpane's setPage(URL url) method) does not have the cookies that were retrieved using the httpclient. My question is - how can I somehow transfer the cookies received with httpclient so that my JEditorPane can display URLs from the site?
I'm beginning to think it's not possible and I should try and logon using normal Java URLconnection etc but would rather stick with httpclient as it's more flexible (I think). Presumably I would still have a problem with the cookies??
I had thought of extending the JEditorPane class and overriding the setPage() but I don't know the actual code I should put in it as can't seem to find out how setPage() actually works.
Any help/suggestions would be greatly appreciated.
Dave
As I mentioned in the comment, HttpClient and the URLConnection used by the JEditorPane to fetch the URL content don't talk to each other. So, any cookies that HttpClient may have fetched won't transfer over to the URLConnection. However, you can subclass JEditorPane like so :
final HttpClient httpClient = new DefaultHttpClient();
/* initialize httpClient and fetch your login page to get the cookies */
JEditorPane myPane = new JEditorPane() {
protected InputStream getStream(URL url) throws IOException {
HttpGet httpget = new HttpGet(url.toExternalForm());
HttpResponse response = httpClient.execute(httpget);
HttpEntity entity = response.getEntity();
// important! by overriding getStream you're responsible for setting content type!
setContentType(entity.getContentType().getValue());
// another thing that you're now responsible for... this will be used to resolve
// the images and other relative references. also beware whether it needs to be a url or string
getDocument().putProperty(Document.StreamDescriptionProperty, url);
// using commons-io here to take care of some of the more annoying aspects of InputStream
InputStream content = entity.getContent();
try {
return new ByteArrayInputStream(IOUtils.toByteArray(content));
}
catch(RuntimeException e) {
httpget.abort(); // per example in HttpClient, abort needs to be called on unexpected exceptions
throw e;
}
finally {
IOUtils.closeQuietly(content);
}
}
};
// now you can do this!
myPane.setPage(new URL("http://www.google.com/"));
By making this change, you'll be using HttpClient to fetch the URL content for your JEditorPane. Be sure to read the JavaDoc here http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JEditorPane.html#getStream(java.net.URL) to make sure that you catch all the corner cases. I think I've got most of them sorted, but I'm not an expert.
Of course, you can change around the HttpClient part of the code to avoid loading the response into memory first, but this is the most concise way. And since you're going to be loading it up into an editor, it will all be in memory at some point. ;)
Under Java 5 & 6, there is a default cookie manager which "automatically" supports HttpURLConnection, the type of connection JEditorPane uses by default.
Based on this blog entry, if you write something like
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_NONE);
CookieHandler.setDefault(manager);
seems enough to support cookies in JEditorPane.
Make sure to add this code before any internet communication with JEditorPane takes place.

Categories