I want to check the header of the request whether it contains a certain header or not before continuing with the body. For example, I want to check whether a multipart/form-data contains "Authorization" in the header or not. If it is not then there is no need to continue with uploading the multipart body which are generally quite large for file uploading.
Does servlet allow you to do this? I have tried to search on google randomly but there is no luck. Here is the code i try in my servlet but it still continues with recieving the body before this doPost method is called. It seems that the stream is fully received before the servlet is invoked.
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
if (request.getHeader("Authorization") == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
out.println("Status: " + HttpServletResponse.SC_UNAUTHORIZED + " - UNAUTHORIZED");
return;
}
// ... the rests
}
That's the limitation of HTTP. You can't send a response when the request hasn't been read fully to end.
RFC 2616 says:
An HTTP/1.1 (or later) client sending a message-body SHOULD monitor the network connection for an error status while it is transmitting the request. If the client sees an error status, it SHOULD immediately cease transmitting the body.
So I disagree, this is not a HTTP limitation but a servlet one.
Related
I have a Java Servlet application running on JBoss 4 and this application receives POST request from another service. I want to acknowledge back to this service before processing. Is it fine to do the following?
protected void doPost(HttpServletRequest req, HttpServletResponse res) {
readReceivedPOSTData();
//send response
PrintWriter out = res.getWriter();
out.print("ack");
out.close();
//Process
processData(); //takes long time
}
I appreciate your help. Thank you.
The basis is ok.
Just some tips:
Use an identifier in the request so you can check in the future the status of that request.
Start another thread to process the data or use a jms queue
remember that you can't write additional data to the response in the processData() method
I'm working on servlet page that renders content based on geo-location, and I want to use both sendRedirect and forward together; e.g; you browse example.com/aPage.jsp from France; first I want the servlet to redirect you to example.com/fr/aPage.jsp and then forward you to the resources page.
This is what I have in my servlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
....
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
// after redirect forward the resources page
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
...
}
But I get:
java.lang.IllegalStateException: Cannot forward after response has been committed
I know the error appears because I can't use both sendRedirect and forward one after another, but I don't know how to achieve what I want (as described above) without this.
any help?
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
// after redirect forward the resources page
After that line , Your response start writing to clinet.
And you are trying to add additional data to it.
The server has already finished writing the response header and is writing the body of the content, and which point you are trying to write more to the header - of course it cant rewind.
So,Thumb rule while dealing with servlet is
Finish your logic before redirect or forward add return statement.So execution ends there .
When you call
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
you are sending your client a 302 HTTP status code with the location to redirect to. Your client then needs to make a new HTTP request to that location. Whichever Servlet is supposed to handle the path REDIRECT_URL_BASED_ON_GEO should then use the RequestDispatcher to forward to the resource described by RESOURCES_PAGE.
To better explain your exception
java.lang.IllegalStateException: Cannot forward after response has been committed
a committed response is a response where HTTP headers are already sent. If we look at your code
response.sendRedirect(REDIRECT_URL_BASED_ON_GEO);
After this line, you've already sent the response along with the headers (302).
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
After these lines, you're asking the resource RESOURCES_PAGE to finish processing the request. That includes writing HTTP headers and body. But the request has already been processed and a response has already been sent, so it will fail, throwing the exception.
You have to be aware that a redirect is a complete response to the browser and the browser will in turn issue a new request to the url you redirected to. Even though you can't really sse it when dealing with the browser you always have to be aware that this is what happens.
Now, if you use the same controller for the second request you have to check wether a redirect is necessary or you can now do the forward instead.
if (!path.startsWith(locationPrefix)) {
response.sendRedirect(locationPrefix + path);
return;
} else {
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
return;
}
Of course it would be nicer to have a distinct controller per request, but depending of url structure and framework this is not always possible.
Once you redirect, the servlet you're working on is no longer in control. You need to get the servlet that is the target of the redirect to recognize the correct condition to forward and then call forward there, with similar code:
RequestDispatcher view = request.getRequestDispatcher(RESOURCES_PAGE);
view.forward(request, response);
Even if it's the same servlet, it's a new invocation of the servlet's doGet( or other similar method.
So, I am constructing a URL from values from a database. Now, I want to make sure that the response headers are what I specify for this URL. How do I achieve this?
For instance, if I construct a URL such as www.google.com/username=ak&password=bk, I want to make sure that the connection is keep alive for the response that you get when you hit the URL. How do I do this within JSP/Java?
The reason being, I'm trying to render a video on an iOS device from my CMS however this doesn't work and from what I have read, the response headers must be set. How do I set response headers for a URL that I might hit?
The following method is how I am setting the response however the response is not the url I make. The URL I make is something like www.uisghsfgsgsfg.com/cs/sksjdgs/appl. I am confused as to what the response means in the context of this page.
class URLConstructor extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Connection", "Keep-Alive");
ByteArrayOutputStream byteStream =
new ByteArrayOutputStream(512);
response.setContentLength(byteStream.size());
response.addHeader("Connection", "Keep-Alive");
}
}
Assumption: You have access to the server which transmits the video.
The code which transmits the video to your client (IOS device) should set the response headers before sending the response(video content). If it is a Java program which serves the request for the video, you can set the appropriate header in the Servlet API (See Martin's link).
Hope that helps.
I have a simple test client-server app. Client is html/javascript, server - Java Servlet
First of all I want to test request/response mechanism. Therefore I have used a simple code for cliet(jQuery):
$.get ("http://localhost:8081/TestProject/BasicServlet",
function(data) {
alert('Data:' +data);
}
);
And on the server side:
protected void doGet(HttpServletRequest req, HttpServletResponse res) ... {
String callBack = "TestCallback";
res.setContentType("text/html");
ServletOutputStream out = res.getOutputStream();
out.write(callBack.getBytes("UTF-8"));
out.flush();
}
So, Servlet catches request from client, but I have a problem with response, response header looks good, with character attributes, but I don't receive the callBack data
As response in Firebug I have 3 tabs, Header, Answer, HTML. Answer and HTML are empty
EDIT:
I have found a Problem: it was Access-Control-Allow-Origin violation.
Thanks for help !
As per the documentation in here
http://download.oracle.com/javaee/6/api/javax/servlet/ServletResponse.html#getOutputStream
is used for sending binary data. So my guess is that Content-Type header is set as some MIME type which is not recognized by jQuery. I suggest you check whether the Content-Type header is still "text/html" in the response using FireBug, or use
PrintWriter writer = res.getWriter();
writer.write(callBack);
writer.flush();
By the way, for sending textual data using PrintWriter is the recommended approach.
Try out.print() instead of out .write() you will get the response in your ajax call.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String text = "some text";
response.setContentType("text/plain"); // Set content type of the response so that jQuery knows what it can expect.
response.setCharacterEncoding("UTF-8"); // You want world domination, huh?
response.getWriter().write(text); // Write response body.
}
If I use this servlet , where request variable will have the url of the API of the website . Then how do I capture the response ? I would want to know what is the code to do that , and is this the right way to go about it when trying to build a JSP page that deals with interacting with an API of a website and showing data ?
You're confusing things. The HttpServletRequest is the HTTP request which the client (the webbrowser) has made to reach the servlet. The HttpServletResponse is the response which you should use to send back the result to the client (the webbrowser).
If you want to fire a HTTP request programmatically, you should use java.net.URLConnection.
URLConnection connection = new URL("http://example.com").openConnection();
InputStream input = connection.getInputStream(); // This contains the response. You need to convert this to String or some bean and then display in JSP.
See also:
How to use java.net.URLConnection to fire and handle HTTP requests