Proxy Servlet for HTTPS - java

I have a secure site that needs to display images coming from external non-https URLs on certain pages. I want to create a servlet that is used only as a proxy to pass the image data to the pages. One way is to use Apache's HttpClient to download the image data and then use IOUtils.copy to copy the data to the servlet's response.
Is there a simpler way?
UPDATE: The reason for this is to avoid browser warnings.

This is what I ended up using:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String url = request.getParameter("url");
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
InputStream inputStream = httpEntity.getContent();
response.setContentType("image/jpeg");
IOUtils.copy(inputStream, response.getOutputStream());
} catch (Exception e) {
AppLogger.log(e);
}
}
If anyone has a better way to accomplish this, please post it.

If I understand well, you don't need anything like that, just return the references to the images or audio, or anything else in your HTML response and the browser will take care of make request to the server that contains each of the resources, if they're reachable, they will be displayed on the client.

Related

Apache httpClient retrying POST request while ignoring timeouts

I'm currently trying to build an OSGi service that sends a POST request to a defined API. This API is used to virus-scan a file which is contained in the request body (JSON) as Base64 string.
For this, I am using Apache HttpClient contained in Adobe AEM uberjar v6.4.0
My current implementation works fine for smaller files (<2 MB), but as filesize gets bigger, the behaviour gets strange:
When I upload a 9 MB file, the request executes for ~1 minute, then gets a HTTP400 as response and afterwards retrys the request 7 times.
I tried to use a timeout with the request. If the timeout is below 60.000ms, a TimeoutException is thrown, if it's greater than 60.000ms, I get a HTTP400 Bad Request. I guess the latter is the APIs fault which I need to clarify.
However, in both cases after the exception is thrown, httpClient retries the request and I have not been able to prevent that since. I'm struggeling with many deprecated "HowTo's" on the web and now I'm here.
I have shortened the code a bit, as it's somehow big (mostly removing debug messages and some "if... return false" at the beginning). My Code:
public boolean isAttachmentClean(InputStream inputStream) throws IOException, JSONException, ServiceUnavailableException {
//prevent httpClient from retrying in case of an IOException
final HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false);
HttpClient httpClient = HttpClients.custom().setRetryHandler(retryHandler).build();
HttpPost httpPost = new HttpPost(serviceUrl);
httpPost.setHeader("accept", "application/json");
//set some more headers...
//set timeout for POST from OSGi Config
RequestConfig timeoutConfig = RequestConfig.custom()
.setConnectionRequestTimeout(serviceTimeout)
.setConnectTimeout(serviceTimeout)
.setSocketTimeout(serviceTimeout)
.build();
httpPost.setConfig(timeoutConfig);
//create request body data
String requestBody;
try {
requestBody = buildDataJson(inputStream);
} finally {
inputStream.close();
}
HttpEntity requestBodyEntity = new ByteArrayEntity(requestBody.getBytes("UTF-8"));
httpPost.setEntity(requestBodyEntity);
//Execute and get the response.
HttpResponse response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() != HttpServletResponse.SC_OK){
httpPost.abort();
throw new ServiceUnavailableException("API not available, Response Code was "+ response.getStatusLine().getStatusCode());
}
HttpEntity entity = response.getEntity();
boolean result = false;
if (entity != null) {
InputStream apiResult = entity.getContent();
try {
// check the response from the API (Virus yes or no)
result = evaluateResponse(apiResult);
} finally {
apiResult.close();
}
}
return result;
}
"buildDataJson()" simply reads the InputStream and creates a JSON needed for the API call.
"evaluateResponse()" also reads the InputStream, transforms it into a JSON and checks for a property named "Status:" "Clean".
I'd appreciate any tipps on why this request is retried over and over again.
/edit: So far, I found that Apache httpClient has some default mechanism that retries a request in case of an IOException - which is what I get here. Still, I have not found a solution on how to deactivate these retries.

Embedding a File Attachment in JSON Object

Is it possible to embed a file attachment in a JSON Object. I have a HTML Form, which has several text field inputs and a file attachment. I want to send a JSON Object wrapping all these form data (including the file attachment) to the server.
Are there any particular libraries in Java available to do that? Can you give possible solution for this.
Thanks
If you want to send the actual data of the file, you'd probably want to encode it as a base64 string and send that in your JSON - see fiddle for example of encoding it in javascript:
http://jsfiddle.net/eliseosoto/JHQnk/
Then you could do the opposite on your server-side using whatever language and/or libraries are appropriate.
Use MultipartEntity, someone else posted a similar question: How to send file in JSON on android?
You could also consider saving the files on the server and sending a path/url to the file location where the other server can access them.
public String SendToServer(String aUrl,File Filename)
{
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(filename);
try
{
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("file", new FileBody(Filename));
entity.addPart("video-title", new StringBody("Video"));
entity.addPart("video-type", new StringBody("1"));
httpPost.setEntity(entity);
HttpContext context = new BasicHttpContext();
// Bind custom cookie store to the local context
context.setAttribute(ClientContext.COOKIE_STORE, Globals.sessionCookie);
HttpResponse response = httpClient.execute(httpPost, context);
HttpEntity resEntity = response.getEntity();
String Response = "";
if (response != null)
{
Response = EntityUtils.toString(resEntity);
}
return Response;
}
catch (IOException e)
{
e.printStackTrace();
}
return "Exception";
}

servlet response to android device

I am in a ditch since last few days trying out to get this,but not able to bring out any desired results.I will try to make myself clear that what i am looking for in following points:
I am working on android app,that will update the location of the user on the server using servlets(on my localhost).There is no problem regarding this,all is working fine.
The real problem that came in my way was when i was trying to get response from server back to android device,i just want to return a simple string,or something like that,Most likely a parameter,that will be utilized by the android app.Then i came to know about the json thing that i have to use it for doing what i am looking for.I have searched a lot about it,found some code too,but not able to use it well,
So my questions are
Is it possible to retrieve response from the servlet,and extract the required values from it without using json or any parsing technique,because i needed something like a single string only.
HttpClient client=new DefaultHttpClient();
HttpGet request=new HttpGet();
URI address=new URI("http://xxx.xxx.xxx.xxx:8080/MyServlet");
request.setUri(address);
HttpResponse response=client.execute(request);
The code from the android device requesting the response and the servlet are shown above,however when i call the toString method on response.toString() in android device,it yield me a string with some sequence of numbers,which are of no use to me.
HELP! HELP! HELP!
A simple example of it might help me up,
You could use a servlet that generates plain text result without any encoding technique.
On the server side, just replace your doGet function to look like that:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello World");
}
On the client side, you could use the following code:
try {
final HttpClient httpClient = new DefaultHttpClient();
final HttpGet httpGet = new HttpGet("http://SERVLET_URL/");
HttpResponse response = httpClient.execute(httpGet);
final HttpEntity entity = response.getEntity();
Log.i(TAG, "Servlet Result: " + EntityUtils.toString(entity));
} catch (ClientProtocolException e) {
Log.e(TAG, "ClientProtocolException", e);
} catch (ParseException e) {
Log.e(TAG, "ParseException", e);
} catch (IOException e) {
Log.e(TAG, "IOException", e);
}

How to access content at the server end?

I have used the following code in my client:
HttpPost post = new HttpPost(url);
post.setEntity(new ByteArrayEntity(myString.getBytes("UTF8")));
HttpResponse response = this.execute(post);
I would now like to access the string on the server end. The handle method looks as follows:
public void handle(String target, Request baseRequest, HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException { ... }
The request only lets me access the content length and type but not the content itself. Any pointers?
I'm using java as a pl and the built in classes from javax.servlet.
You've set the string as the sole HTTP request body instead of as a request parameter for some reason. So, to get it, you need to read the whole HTTP request body. This is in the servlet available by
InputStream input = request.getInputStream();
// Read it into a String the usual way (using UTF-8).
Note that this would return an empty stream when it's already been read beforehand, e.g. by calling getParameter() beforehand on the very same request which would implicitly parse the POST request body for that.
The more sane approach would be to send it as a normal URL encoded request parameter as follows (exactly like as those HTML forms by default do)
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("myString", myString));
post.setEntity(new UrlEncodedFormEntity(params));
so that you can in the servlet just do
String myString = request.getParameter("myString");
// ...

Submit an httpRequest method post to an apache server with java se

i'm trying to use a website from my java application as i'd do through my browser; it's the first time i'm trying something like this and i'm afraid i'm missing something.
I'm using apache httpcore libraries to do the http requests with the post method, with wireshark i've seen the parameters in the post request and i've added them to the request i do with java; the same for the headers.
If i sniff the request made with java i can't capture the http post request, but only the tcp traffic.
This is how i do the request:
HttpPost httpPost = new HttpPost("http://xxx.xxx");
httpPost.setHeader("Host", "xxx.xxx:xxxx");
.
.
.
HttpParams params = new BasicHttpParams();
params.setParameter("aaaa", "bbbb");
.
.
.
HttpResponse response = httpclient.execute(httpPost);
Am i missing something?
I should check something else?
Thank you very much for the help!
You have to supply a body with your post request, which you do so by calling the .setEntity(HttpEntity) method on your HttpPost.
private void sendToPostProxy(HttpServletRequest request,
HttpServletResponse response) throws IOException {
//the url to forward too
String url = "http://127.0.0.1:"+proxyPort+request.getRequestURI()
+(request.getQueryString()==null?"":"?"+request.getQueryString());
HttpPost get = new HttpPost(url);
//I am streaming requests straight through, but there are many Entity types you can use
get.setEntity(new InputStreamEntity(request.getInputStream(), request.getContentLength()));
sendToProxy(request, response, get);
}
private void sendToProxy(HttpServletRequest request,
HttpServletResponse response,HttpRequestBase get) throws IOException {
DefaultHttpClient client = new DefaultHttpClient();
Enumeration headers = request.getHeaderNames();
//copy headers
while(headers.hasMoreElements()){
String next = String.valueOf(headers.nextElement());
String header = request.getHeader(next);
if (!get.containsHeader(next)&&!"Content-Length".equalsIgnoreCase(next))
get.addHeader(next, header);
}
try{
//perform post
HttpResponse proxied = client.execute(get);
//set client headers
for (Header h : proxied.getAllHeaders()){
response.setHeader(h.getName(), h.getValue());
}
//stream to client
HttpEntity body = proxied.getEntity();
body.writeTo(response.getOutputStream());
response.setStatus(HttpServletResponse.SC_OK);
}catch(Exception e){
e.printStackTrace();
get.abort();
}
}

Categories