RequestDispatcher for remote server? - java

I am trying to create a HttpServlet that forwards all incoming requests as is, to another serlvet running on a different domain.
How can this be accomplished? The RequestDispatcher's forward() only operates on the same server.
Edit: I can't introduce any dependencies.

You can't when it doesn't run in the same ServletContext or same/clustered webserver wherein the webapps are configured to share the ServletContext (in case of Tomcat, check crossContext option).
You have to send a redirect by HttpServletResponse.sendRedirect(). If your actual concern is reusing the query parameters on the new URL, just resend them along.
response.sendRedirect(newURL + "?" + request.getQueryString());
Or when it's a POST, send a HTTP 307 redirect, the client will reapply the same POST query parameters on the new URL.
response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("Location", newURL);
Update as per the comments, that's apparently not an option as well since you want to hide the URL. In that case, you have to let the servlet play for proxy. You can do this with a HTTP client, e.g. the Java SE provided java.net.URLConnection (mini tutorial here) or the more convenienced Apache Commons HttpClient.
If it's GET, just do:
InputStream input = new URL(newURL + "?" + request.getQueryString()).openStream();
OutputStream output = response.getOutputStream();
// Copy.
Or if it's POST:
URLConnection connection = new URL(newURL).openConnection();
connection.setDoOutput(true);
// Set and/or copy request headers here based on current request?
InputStream input1 = request.getInputStream();
OutputStream output1 = connection.getOutputStream();
// Copy.
InputStream input2 = connection.getInputStream();
OutputStream output2 = response.getOutputStream();
// Copy.
Note that you possibly need to capture/replace/update the relative links in the HTML response, if any. Jsoup may be extremely helpful in this.

As others have pointed out, what you want is a proxy. Your options:
Find an open-source Java library that does this. There are a few out there, but I haven't used any of them, so I can't recommend any.
Write it yourself. Shouldn't be too hard, just remember to deal with stuff like passing along all headers and response codes.
Use the proxy module in Apache 2.2. This is the one I'd pick, because I already know that it works reliably.

Jetty has a sample ProxyServlet implementation that uses URL.openConnection() under the hood. Feel free to use as-is or to use as inspiration for your own implementation. ;-)
Or you can use Apache HttpClient, see the tutorial.

Related

with java downloaded file is too small

i use this code snippet to download some mp3-files:
File target = /*...*/;
InputStream in = new URL(link).openStream();
Files.copy(in, target.toPath(), StandardCopyOption.REPLACE_EXISTING);
it usually works fine, but now i have a series of files, that are way too small and don't work. for example: https://kritisches-denken-podcast.de/wp-content/uploads/2019/01/KDP-Episode-17-Selbsterhaltungstherapie.mp3 should be about 46MB(when i download it via browser) but is only 315 Bytes when i download it with the code above on my android.
The URL has a redirect built into it. Usually such redirects, especially for URLs targeted at non-browsers (Which an mp3 URL clearly is), are served up as an HTTP 301 'Moved Permanently' (and sometimes 302 'Moved Temporarily'), with the right URL sent along in the Location header. The text you see (the 315 bytes you download) is merely 'fallback' HTML that also state the content has moved. There is no need to parse this, fortunately.
The HTTP 'browser' of URL's openStream code is very basic and does not follow redirects. You need an API that does. URLConnection (also from the core libs) can do it, but it does not follow redirects if the redirect switches from http to https or vice versa, so you might not wanna do that. Just in case you do:
File target = /*...*/;
HttpURLConnection con = (HttpURLConnection) new URL(link).openConnection();
con.setInstanceFollowRedirects(true);
try (InputStream in = con.getInputStream()) {
Files.copy(in, target.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
If the above is no good (presumably due to HTTP/HTTPS redirect issue) I suggest picking up a real HTTP client, which the standard API does not provide. I suggest OkHttp.

How to send special character via HTTP post request made in Java

I need to send data to another system in a Java aplication via HTTP POST method. Using the Apache HttpClient library is not an option.
I create a URL, httpconection without problems. But when sending special character like Spanish Ñ, the system complains it is receiving
Ñ instead of Ñ.
I've read many post, but I don't understand some things:
When doing a POST connection, and writing to the connection object, is it mandatory to do the URLEncode.encode(data,encoding) to the data being sent?
When sending the data, in some examples I have seen they use the
conn.writeBytes(strData), and in other I have seen conn.write(strData.getBytes(encoding)). Which one is it better? Is it related of using the encode?
Update:
The current code:
URL url = new URL(URLstr);
conn1 = (HttpsURLConnection) url.openConnection();
conn1.setRequestMethod("POST");
conn1.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn1.getOutputStream());
wr.writeBytes(strToSend);//data sent
wr.flush();
wr.close();
(later I get the response)
strToSend has been previously URLENCODE.encode(,"UTF-8")
I still don't know if I must use urlencode in my code and/or setRequestProperty("Contentype","application/x-www-formurlencode");
Or if I must use .write(strToSend.getByte(??)
Any ideas are welcome. I am testing also the real server (I dont know very much about it)

How to download file from web site having liferay portlet using java code

i'm trying to download a file from a site , this site has a life ray server
i have been reading to much about but all describe how to configure a server not how to read from , all examples i saw has HTTPServletRequest which needs a request input how can i transfer a URL to a request ,from where to start at least .
in other words :i have the URL , in the webpage i select a date and a download like is generated , how can i make it down in java ????
i tried this:
HttpServletRequest request = PortalUtil.getHttpServletRequest(PortletRequest);
so how to link my URL to PortletRequest
If you have the URL of the download the only thing you need is to perform a client request against that URL.
First thing you should try to be sure that the URL you have is the one that will give you the expected results is try to paste it in a new browser window and verify that the download starts.
Then, if you want to perform that download through Java you can do very easily using the URL and URLConnection (HttpURLConnection in this case) classes:
String urlString = "..."; // Your URL
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
InputStream stream = conn.getInputStream();
// Read the data from the stream
}
You could also do the same using Apache HTTP Client.
Note: PortalUtil.getHttpServletRequest(...) is used internally by Liferay and you won't have any access to that API if you are doing a client request.
If you're writing a portlet, by design you don't get access to the HttpServletRequest.
What you can do is to utilize the "resource-serving" lifecycle phase of a portlet. There you get access to a ResourceRequest and ResourceResponse object. Those objects behave almost like a HttpServletRequest/-Response object
As you don't name the framework that you're using: javax.portlet.GenericPortlet.serveResource() is the method that you want to override in the pure JSR-286 API.
On the UI side, <portlet:resourceURL/> will provide the URL to your portlet's resource handling method.
This should provide you with enough google-food to find tutorials on how to implement different lifecycle phases - I can't judge the required level of detail you need. Note that Liferay has quite a few sample portlets that you can utilize as a source for sample code.
Edit: Following your comment below, let me give you some pseudo code (just typed here, never compiled/run):
on a jsp frontend, e.g. view.jsp:
Download File
Then, in your portlet, assuming you're implementing javax.portlet.GenericPortlet in one way or another (e.g. indirectly through Liferay's MVCPortlet or any other superclass):
public class MyPortlet extends GenericPortlet {
....
#Override
public void serveResource(ResourceRequest request, ResourceResponse response) {
// implement the file streaming here,
// use ResourceResponse the way you find illustrated
// in samples for HttpServletResponse
}

Java: handling webcal protocol

I'm trying to download - or even just open a stream - to a calendar located at webcal://www.somewhere.com/foo?etc=bar.
The Java URL class is throwing a "unknown protocol: webcal" exception when I do:
URL url = new URL("webcal://...");
How can I tell the URL class that it should just use HTTP as trasport protocol even if the web resource is located somewhere behind a webcal:// protocol?
Or, in any case, how can I get my calendar downloaded?
Please, bear in mind that the web server I'm calling does not serve the calendar if I try to replace the "webcal://" with "http://".
As far as I understand, Apple's use of "webcal" really is just a synonym for "http"; so it's supposed to work.
The "webcal://" is an unofficial URI scheme, see Wikipedia article on it.
As such it might stand for one or another back end implementation - e.g. the web server you are calling might be using any of the mentioned protocol implementations, such as WebDAV, CalDAV or OpenDAV
However if all you want is to read the contents of the file, then any HTTP client should do the trick, because the above mentioned protocols are based on HTTP.
Here is an example on how to read a remote iCal using URL's own mechanism for opening HttpURLConnection :
URL calendarURL = new URL("http://www.facebook.com/ical/b.php?uid=myUID&key=myKEY");
URLConnection connection = calendarURL.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while (reader.ready()) {
System.out.println(reader.readLine());
}
As you can see I have changed the original URL from
webcal://www.facebook.com/ical/b.php?uid=MYUID&key=MYKEY
to
http://www.facebook.com/ical/b.php?uid=MYUID&key=MYKEY
, because we use a java.net.URL and by default Java does not recognize this protocol. If indeed the web server you want to contact only serves the content over webcal:// then you might need to use the appropriate client (based on the exact protocol implementation the server uses). For example there are a multitude of frameworks that provide WebDAV client capabilities, such as JackRabbit, Sardine, etc.
If you provide more information on the type of server we can dig further.

Use Server cache for 15 minutes

I want to use server cache for 15 minutess so what i have to use in setRequestProperty() ?
Please Help me..
Here is my code which i used..
private HttpURLConnection httpCon = null;
httpCon = (HttpURLConnection) httpUrl.openConnection();
httpCon.setRequestMethod("GET");
httpCon.setRequestProperty("Connection", "Keep-Alive");
httpCon.setRequestProperty("Pragma","public");
httpCon.setRequestProperty("Cache-Control","maxage=900");
httpCon.setUseCaches(true);
You are telling the server you are willing for it to cache responses, but there's no guarantee that the server will do that or is enabled to do that (unless you control the server also and implement that).
You can also try setting up an intermediate HTTP cache the client and server, such as a proxy cache such as Varnish, Pound, or Squid.
Lastly, you can do browser caching on your own, which is supported the the Android java.net package but doesn't have a default implementation. To do this:
-Check out HttpURLConnection which details (in the "Response Caching" section) that you must implement ResponseCache and call setDefault.
-Also check out ResponseCache Example which has examples of this, and something quirky to watch out for at the end (which may or may not still be true).
Good luck!
Instead of using the HttpConnection, use DefaultHttpClient and CachingHttpClient (part of Apache Http Client, bundled by default with Android).
Have a look at http://hc.apache.org/httpcomponents-client-ga/tutorial/html/caching.html to get more details on how to use caching.

Categories

Resources