How to get external IP successfully - java

After reading: Getting the 'external' IP address in Java
code:
public static void main(String[] args) throws IOException
{
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
}
I thought I was a winner but I get the following error
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: http://automation.whatismyip.com/n09230945.asp
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at getIP.main(getIP.java:12)
I think this is because the server isnt responding quick enough, is there anyway to ensure that it will get the external ip?
EDIT: okay so its getting rejected, anyone else know of another site that can do the same function

public static void main(String[] args) throws IOException
{
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection();
String str = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
str = reader.readLine();
System.out.println(str);
}

Before you run the following code take a look at this: http://www.whatismyip.com/faq/automation.asp
public static void main(String[] args) throws Exception {
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
URLConnection connection = whatismyip.openConnection();
connection.addRequestProperty("Protocol", "Http/1.1");
connection.addRequestProperty("Connection", "keep-alive");
connection.addRequestProperty("Keep-Alive", "1000");
connection.addRequestProperty("User-Agent", "Web-Agent");
BufferedReader in =
new BufferedReader(new InputStreamReader(connection.getInputStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
}

While playing with Go I saw your question. I made a quick App on Google App Engine using Go:
Hit this URL:
http://agentgatech.appspot.com/
Java code:
new BufferedReader(new InputStreamReader(new URL('http://agentgatech.appspot.com').openStream())).readLine()
Go code for the app which you can copy and make your own app:
package hello
import (
"fmt"
"net/http"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, r.RemoteAddr)
}

Some servers has triggers that blocks access from "non-browsers". They understand that you are some kind of automatic app that can do a DOS attack. To avoid this, you can try to use a lib to access the resource and set the "browser" header.
wget works in this way:
wget -r -p -U Mozilla http://www.site.com/resource.html
Using Java, you can use the HttpClient lib and set the "User-Agent" header.
Look the topic 5 of "Things To Try" section.
Hope this can help you.

A 403 response indicates that the server is explicitly rejecting your request for some reason. Contact the operator of WhatIsMyIP for details.

We've set up CloudFlare and as designed they're challenging unfamiliar useragents. If you can set your UA to something common, you should be able to gain access.

You can use another web service like this; http://freegeoip.net/static/index.html

Using the Check IP address link on AWS worked for me.Please note that MalformedURLException,IOException are to be added as well
public String getPublicIpAddress() throws MalformedURLException,IOException {
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection();
String str = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
str = reader.readLine();
return str;
}

This is how I do it with rxJava2 and Butterknife. You'll want to run the networking code in another thread because you'll get an exception for running network code on the main thread!
I use rxJava instead of AsyncTask because the rxJava cleans up nicely when the user moves on to the next UI before the thread is finished. (this is super useful for very busy UI's)
public class ConfigurationActivity extends AppCompatActivity {
// VIEWS
#BindView(R.id.externalip) TextInputEditText externalIp;//this could be TextView, etc.
// rxJava - note: I have this line in the base class - for demo purposes it's here
private CompositeDisposable compositeSubscription = new CompositeDisposable();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_wonderful_layout);
ButterKnife.bind(this);
getExternalIpAsync();
}
// note: I have this code in the base class - for demo purposes it's here
#Override
protected void onStop() {
super.onStop();
clearRxSubscriptions();
}
// note: I have this code in the base class - for demo purposes it's here
protected void addRxSubscription(Disposable subscription) {
if (compositeSubscription != null) compositeSubscription.add(subscription);
}
// note: I have this code in the base class - for demo purposes it's here
private void clearRxSubscriptions() {
if (compositeSubscription != null) compositeSubscription.clear();
}
private void getExternalIpAsync() {
addRxSubscription(
Observable.just("")
.map(s -> getExternalIp())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe((String ip) -> {
if (ip != null) {
externalIp.setText(ip);
}
})
);
}
private String getExternalIp() {
String externIp = null;
try {
URL connection = new URL("http://checkip.amazonaws.com/");
URLConnection con = connection.openConnection(Proxy.NO_PROXY);
con.setConnectTimeout(1000);//low value for quicker result (otherwise takes about 20secs)
con.setReadTimeout(5000);
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
externIp = reader.readLine();
} catch (Exception e) {
e.printStackTrace();
}
return externIp;
}
}
UPDATE - I've found that URLConnection is really quite shit; it'll take a long time to get a result, not really time out very well, etc. The code below improves the situation with OKhttp
private String getExternalIp() {
String externIp = "no connection";
OkHttpClient client = new OkHttpClient();//should have this as a member variable
try {
String url = "http://checkip.amazonaws.com/";
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
ResponseBody responseBody = response.body();
if (responseBody != null) externIp = responseBody.string();
} catch (IOException e) {
e.printStackTrace();
}
return externIp;
}

Related

FileWriter closes websocket connection?

I am new to server programming and websockets and I've learnt a little bit of Java 8 this year. In school we had a project where a client webpage opens your webcam, takes a photo of a barcode and then shows a photo and the nutritional value of said product. You can also just send a raw barcode number and that is what is done in this example
My side of the project was to implement a java websocket server (the backend) using the glassfish tyrus library, then receiving the number of the barcode in string format and making a request to openfoodfacts.org using their api. Finally I parsed the json file and sent it back as string format so the client app can read the string and show the correct information (product name, image url, etc)
My code is organized into two files, Serveur.java establishes a websocket server for the client to connect to and ProduitApi.java gets the information from openfoodfacts.org with the given barcode from the client.
public class Serveur {
#javax.websocket.server.ServerEndpoint(value = "/websocket")
public static class EndPoint {
#javax.websocket.OnClose
public void onClose(javax.websocket.Session session, javax.websocket.CloseReason close_reason) {
System.out.println("onClose: " + close_reason.getReasonPhrase());
}
#javax.websocket.OnError
public void onError(javax.websocket.Session session, Throwable throwable) {
System.out.println("onError: " + throwable.getMessage());
}
#javax.websocket.OnMessage
public void onMessage(javax.websocket.Session session, String message) {
System.out.println("Message from client: " + message);
//Creation du produit avec le message du client
try {
ProduitApi produit = new ProduitApi(message);
session.getBasicRemote().sendText(produit.print());
} catch (Exception e) {
e.printStackTrace();
}
}
#javax.websocket.OnOpen
public void onOpen(javax.websocket.Session session, javax.websocket.EndpointConfig ec) throws java.io.IOException {
System.out.println("OnOpen... " + ec.getUserProperties().get("Author"));
session.getBasicRemote().sendText("{\"Handshaking\": \"Yes\"}");
}
}
public static void main(String[] args) {
Server server;
server = new Server ("localhost", 8025, "/BetterFood", null, EndPoint.class);
try {
server.start();
System.out.println("--- server is running");
System.out.println(java.nio.file.FileSystems.getDefault().getPath("client") );
System.out.print("Please press a key to stop the server.");
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
reader.readLine();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}
}
as you can see, when I receive the 'barcode' message, onMessage() gets called. There I instantiate an object of class ProduitApi to use the barcode to then return the information
This is my ProduitApi file without some unnecessary details
package com.gabi.serveur;
/**
*
* #author gabriel
*/
[imports]
public class ProduitApi {
private java.lang.String barcode;
final private java.net.URL url;
private java.net.URLConnection connection;
JsonObjectBuilder constructeur_objet = Json.createObjectBuilder();
String string_json;
ProduitApi(java.lang.String barcode)throws MalformedURLException, IOException {
this.barcode = barcode;
this.url = new java.net.URL("http://world.openfoodfacts.org/api/v0/product/" + this.barcode + ".json");
connection = url.openConnection();
stream();
}
public void stream() throws IOException{
if (connection != null) {
java.io.InputStreamReader response = new java.io.InputStreamReader(connection.getInputStream());
javax.json.stream.JsonParser parser=javax.json.Json.createParser(response);
while (parser.hasNext()) {
[parsing inputStream into JsonObject]
}
public String print()throws IOException{
string_json = constructeur_objet.build().toString();
System.out.print(string_json);
//FileWriter file = new FileWriter("serveur/src/main/java/com/gabi/serveur/json/final.json");
//file.write(string_json);
//file.close();
return string_json;
}
}
My problem comes from the last function ProduitApi.print() , it is supposed to return the parsed json in string form so I can send it via the sendText() as well as printing the result into my console so I can see if everything went right. As you can see there are somme commented lines; The FileWriter object that I had created was used with the purpose of writing said string to a file in my pc and let me check inside.
HOWEVER
and here is what I don't understand, If I uncomment those lines so that the print function can also write the file to my drive, The Connection Closes and then Opens again
It can be seen in the console where after printing the json string, it prints OnClose, followed by OnOpen Signaling the connection was reset for some reason.
If I remove the FileWriter section, the connection works normally, the client's connection stays open and he can make another request
End of Console Message after request:
...cuits x22 biscuits fourrés - 304g","qte":"304 g","img":"https://images.openfoodfacts.org/images/products/800/050/031/0427/front_fr.177.400.jpg"}onClose: OnOpen... null...
Finally, my question is just why writing to a file makes my program behave this way (resetting the connection). Does it have anything to do with how streams work?
I accidentally commented the filewriter portion when another Ide said it didn't find the file because I had opened the project from a different directory.

How to make a POST REST call asynchronously in Java

I have tried a bunch of libraries to make a REST POST call using HttpConnection in Java asynchronously. I have tried many open source libraries and none of them seems to serve my purpose. Is there any way to do this in core Java.
Without knowing your requirements or expectations:
Here is a simple example without proper error handling which shows how an async HTTP call can be done using Java 8
public static void main(String ... args) throws InterruptedException, ExecutionException, TimeoutException {
Future<Object> futureResult = getObjectAsync();
Object value = futureResult.get(500, TimeUnit.MILLISECONDS);
}
public static Future<Object> getObjectAsync() {
return CompletableFuture.supplyAsync(() -> doHttpCall());
}
static Object doHttpCall() {
try {
HttpURLConnection urlConnection =
(HttpURLConnection) new URL("http://example.net/something").openConnection();
urlConnection.setRequestMethod("POST");
try (OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream())) {
out.write("params as json");
}
try (InputStreamReader in = new InputStreamReader(urlConnection.getInputStream())) {
// convert to Object
return new Object();
}
} catch (IOException e ) {
throw new RuntimeException(e);
}
}

How do I specify a port number dynamically for an HTTPUrl?

I have a project that I am working on. It comes in two parts. For this part, we are supposed to be building the server, client communicator, and other functionality. We are not building the client yet; in order to pass off this part of the project, there is an automated tester that will act as the client. It will specify a random port number and create the server, then call a bunch of methods through the communicator.
The only place that I have access to the port number is when I initialize the server. The server itself has a main method that sets up the server; I have tried storing it as a static variable to access later, but when I try to access it I always get 0 as the port number in the request, which is wrong.
This line is from the ClientCommunicator. Specifically, this is what happens when the "client" calls the validateUser function, which only accepts two arguments: username and password. I cannot pass the port number as an additional argument.
String response = HttpClientHelper.doGetRequest(Helper.BASE_URL +"validateUser?username="+username+"&password="+password,null);
Helper has a static final variable BASE_URL which is currently set to
public static final BASE_URL = "http://localhost:8080/";
Obviously, this is no longer going to work.
The change I would like to make would be to turn the line in my client communicator to
String response = ...(Helper.BASE_URL + (PORT_NUMBER) + "/" +...
where PORT_NUMBER would actually be something like Server.PORT_NUMBER,
and turn BASE_URL to
public static final BASE_URL = "http://localhost:"
However, I'm not sure how I would dynamically add the port number into the doGetRequest. I have tried storing it as a static variable in the server class which gets initialized when the server is started, but if I try to access it that way it ends up defaulting to 0.
My server class (I am not type-checking in this class for the port number, it's done elsewhere):
public class IndexerServer{
public static int port;
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
public static void main(String[] args) throws IOException {
int port = 8080;
if(args.length > 0){
port = Integer.parseInt(args[0]);
}
IndexerServer.port = port;
InetSocketAddress addr = new InetSocketAddress(port);
HttpServer server = HttpServer.create(addr,0);
Helper.BASE_URL+= port + "/";
server.createContext("/validateUser",new ValidateUser());
server.createContext("/getProjects",new GetProjects());
server.createContext("/getSampleImage",new GetSampleImage());
server.createContext("/downloadBatch",new DownloadBatch());
server.createContext("/getFields",new GetFields());
server.createContext("/search",new Search());
server.createContext("/submitbatch",new SubmitBatch());
server.createContext("/images",new ImageDownloader());
server.createContext("/fieldhelp",new HtmlDownloader());
server.createContext("/knowndata",new HtmlDownloader());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
System.out.println("Server is listening on port "+port);
}
}
and the pertinent part of the HTTPHelper
public class HttpClientHelper
{
public static String doGetRequest(String urlString,Map<String,String> headers){
URL url;
HttpURLConnection connection = null;
try {
//Create connection
url = new URL(urlString);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
if(connection.getResponseCode() == 500){
return "failed";
}
//Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
If you don't care about losing the authority or anchor part of the input URL, you can just parse it, break it up and recreate it, replacing the port:
final int PORT = 42;
URL url = new URL(str);
URL newurl = new URL(url.getProtocol(), url.getHost(), PORT, url.getFile());
For example, for the input:
http://user:pass#hello.com:1234/path/file.ext?param=value#anchor
The output is:
http://hello.com:42/path/file.ext?param=value
If you want to preserve the authority / anchor, you'll have to modify the host and output appropriately (url.getAuthority() and url.getRef() will return the parsed components).
Are the server and client communicator two different programs? If so, you can simply pass the port as an extra argument to the client when starting up and compose the string from there.
If both classes are part of the same program you can simply pass the port to HttpClientHelper using Integer.toString(port) when you call this helper. Something along the lines of url = new URL(urlString + port).

How to set HTTP post parameters on a NIO Asynchronous call?

the answer to this must be pretty simple, but I'm still unable to find it. Let's say that I have a working example of Java Asynchronous call that makes use of GET parameters:
final CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
URL url = new URL("http://www.myurl.com?param1=blabla");
try {
final Future<Boolean> future = client.execute(
HttpAsyncMethods.createGet(url),
new MyResponseConsumer(),
null
);
NotifierThread hilo = new NotifierThread(future);
hilo.start();
} finally {
client.close();
}
but what if I want to use POST parameters for "param1" instead of GET?. How can I achieve this?. I was unable to find any method on the HttpAsyncMethods library to do this.
Any help would be appreciated.
Regards
Well, I finally found out how this could be performed and I'm posting it here in case someone else has the same doubt (just as I suspected the answer was not so difficult :-) ):
final CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
client.start();
URL url = new URL("http://www.myurl.com");
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> param:params.entrySet()) {
sb.append(param.getKey()+"="+param.getValue()+"&");
}
if (sb.length() > 0) {
sb = new StringBuilder(sb.substring(0, sb.length()-1));
}
try {
HttpAsyncRequestProducer prod = HttpAsyncMethods.createPost(
BASE_URL+call,
sb.toString(),
ContentType.APPLICATION_FORM_URLENCODED
);
final Future<Boolean> future = client.execute(
prod,
new MyResponseConsumer(),
null
);
NotifierThread hilo = new NotifierThread(future);
hilo.start();
} finally {
client.close();
}
Regards

nearest equivalent of a webpage reload in java

I am taking some data from a database via a servlet and a db handler java class and hosting it at a url. Since the database is changing I'm taking care only to host the changes rather than the entire db data.
I'm getting the required functionality by a browser i.e after every (manual) reload, I'm getting the data as required by me,
1. at the first page load, entire data gets displayed.
2. at subsequent reloads, I get either null data if there is no change in the database, or the appended rows if the database extends. (the database can only extend).
But then in a java program, I'm not getting the same functionality. The java program using HttpUrlConnection.
This is the code for the java client for servlet...
public class HTTPClient implements Runnable {
private CallbackInterface callbackinterface;
private URL url;
private HttpURLConnection http;
private InputStream response;
private String previousMessage = "";
public HTTPClient() {
try {
url = new URL("http://localhost:8080/RESTful-Server/index.jsp");
http = (HttpURLConnection) url.openConnection();
http.connect();
} catch (IOException e) {
}
}
#Override
public void run() {
while (true) {
try {
String currentmessage = "";
response = http.getInputStream();
if (http.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader buffread = new BufferedReader(new InputStreamReader(response));
String line;
for (; (line = buffread.readLine()) != null;) {
currentmessage += line;
}
if ((!currentmessage.equals(previousMessage)
|| !previousMessage.equals(""))
&& !currentmessage.equals("")) {
//this.callbackinterface.event(currentmessage);\
System.out.println(currentmessage + "\t" + previousMessage);
}
previousMessage = currentmessage;
Thread.sleep(2500);
} else {
throw new IOException();
}
} catch (IOException | InterruptedException e) {
System.err.println("Exception" + e);
}
}
}
The shown class is a thread which read the connections every 2.5 s. If it gets something significant in the getline(), it will issue a callback to a worker method, which takes care of remaining things.
I am thinking the issues is because of the class variable conn, and that reload as in the browser is not getting replicated..
Any idea how to do this?
You're basically connecting (requesting) only once and trying to read the response multiple times, while it can be read only once. You basically need to create a new connection (request) everytime. You need to move the creation of the connection by url.openConnection() to inside the loop. The line http.connect() is by the way superfluous. You can safely omit it. The http.getInputStream() will already implicitly do it.
See also:
Using java.net.URLConnection to fire and handle HTTP requests

Categories

Resources