Errorstream in HttpUrlConnection - httpurlconnection

I want to do a POST request to an HTTP Servlet I wrote myself. Good case (HTTP response Code 200) always works fine by using URL.openConnection() method. But when I receive a desired error response code (e.g. 400) then I thought I have to use HttpUrlConnection.getErrorStream(). But the ErrorStream object is null though I am sending data back from the servlet in error case (I want to evaluate this data to generate error messages).
This is what my code looks like:
HttpURLConnection con = null;
try {
//Generating request String
String request = "request="+URLEncoder.encode(xmlGenerator.getStringFromDocument(xmlGenerator.generateConnectRequest(1234)),"UTF-8");
//Receiving HttpUrlConnection (DoOutput = true; RequestMethod is set to "POST")
con = openConnection();
if (con != null){
PrintWriter pw = new PrintWriter(con.getOutputStream());
pw.println(request);
pw.flush();
pw.close();
InputStream errorstream = con.getErrorStream();
BufferedReader br = null;
if (errorstream == null){
InputStream inputstream = con.getInputStream();
br = new BufferedReader(new InputStreamReader(inputstream));
}else{
br = new BufferedReader(new InputStreamReader(errorstream));
}
String response = "";
String nachricht;
while ((nachricht = br.readLine()) != null){
response += nachricht;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
So my question is, why returns getErrorStream() null though status code is 400 (I can see it in the IOException that is thrown when it calls con.getInputStream())
Thanks

From the java documentation on getErrorStream():
Returns the error stream if the connection failed but the server sent useful data nonetheless. The typical example is when an HTTP server responds with a 404, which will cause a FileNotFoundException to be thrown in connect, but the server sent an HTML help page with suggestions as to what to do.
This method will not cause a connection to be initiated. If the connection was not connected, or if the server did not have an error while connecting or if the server had an error but no error data was sent, this method will return null. This is the default.
So if you didn't get to the server (bad url for example) or the server didn't send anything in the response, getErrorStream() will return null.

InputStream inputStream = null;
try {
inputStream = connection.getInputStream();
} catch(IOException exception) {
inputStream = connection.getErrorStream();
}
It is like when you set response header status code as anything beyond 200, the connection object is reset. it will generate SocketTimeoutException while getting the inputstream but when it comes in the catch it gives you the inputstream anyway, what you are expecting.

Digging a little bit into JDK code, I finally find the reason. HttpURLConnection#getErrorStream() returns null when receiving a 401 or 407, not because the noop implementation in the abstract class, but because HttpURLConnection closes/clears the connection immediately if it sees a 401/407 when in streaming mode(i.e., POST). See the source of the concrete implementation of HttpURLConnection: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/net/www/protocol/http/HttpURLConnection.java#1079
That said, when you catch an IOException when calling getInputStream(), the connection to server is already closed and the underlining socket is cleared, so you would always get null when calling getErrorStream().
The other options many have suggested is to check the status code before calling getInputStream or getErrorStream. This won't for 401 and 407 either because the internal errorStream is only set when you call getInputStream, i.e., it's a basically a copy of the inputStream when status code != 200. But again when you call getInputStream, the connection will be closed.

Put the statement conn.setAllowUserInteraction(true); before execute the request and the connection will not be closed, even receiving 401 status.
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setAllowUserInteraction(true); // <<<--- ### HERE
//do something
conn.connect();
boolean isError = (conn.getResponseCode() >= 400);
InputSteam is = isError ? con.getErrorStream() : con.getInputStream();

As suggested in the Android documentation:
String responseString;
try {
responseString = readInputStream(con.getInputStream());
} catch (final IOException e) {
// This means that an error occurred, read the error from the ErrorStream
try {
responseString = readInputStream(con.getErrorStream());
} catch (IOException e1) {
throw new IllegalStateException("Unable to read error body.", e);
}
}
private String readInputStream(final InputStream inputStream) throws IOException {
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
final StringBuilder responseString = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
responseString.append(line);
}
bufferedReader.close();
return responseString.toString();
}

Related

Forward an email(read using JavaMailApi) with Attachments by apache common java api

I'm reading messages from an Outlook webmail and getting a list of Messages('javax.mail.Message'). Now I want to forward these Messages to another email address using a java program.
private void sendTestMail(String from, String subject, String sentDate, Object object, Message message)
throws EmailException, Exception {
MultiPartEmail email = new MultiPartEmail();
email.setHostName(forwardHost);
email.addTo(mailRecipients(to));
email.setFrom(emailFrom);
email.setSubject(subject);
email.setMsg("Testing email by sahil.");
EmailAttachment attachment = new EmailAttachment();
attachment.setPath("c:\\sahil\\test.jpg");
attachment.setDisposition(EmailAttachment.ATTACHMENT);
attachment.setDescription("Picture_of_John");
attachment.setName("John.jpg");
email.attach(attachment);
MimeMultipart multiPart = getMimeMultipart(message);
email.addPart(multiPart);
email.send();
}
If I comment below two lines in above code then it works fine.
MimeMultipart multiPart = getMimeMultipart(message);
email.addPart(multiPart);
But with these two line I'm getting exception.
2020-04-20 15:41:44,271 ERROR com.st.ict.ols.service.impl.ReplyToMessageServiceImpl [main] Inner Exception occurred while processing individual message. Error stacktrace is[org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtpapp1.sgp.st.com:25
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1421)
at org.apache.commons.mail.Email.send(Email.java:1448)
at com.st.ict.ols.service.impl.ReplyToMessageServiceImpl.sendTestMail(ReplyToMessageServiceImpl.java:342)
at com.st.ict.ols.service.impl.ReplyToMessageServiceImpl.processMessage(ReplyToMessageServiceImpl.java:167)
at com.st.ict.ols.service.impl.MessageServiceImpl.processMessage(MessageServiceImpl.java:22)
at com.st.ict.ols.OlsMailSenderApplication.run(OlsMailSenderApplication.java:36)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at com.st.ict.ols.OlsMailSenderApplication.main(OlsMailSenderApplication.java:27)
Caused by: javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.IOException: Exception writing Multipart
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1308)
at javax.mail.Transport.send0(Transport.java:255)
at javax.mail.Transport.send(Transport.java:124)
at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1411)
... 10 more
Caused by: java.io.IOException: Exception writing Multipart
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:83)
at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:884)
at javax.activation.DataHandler.writeTo(DataHandler.java:317)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1652)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:961)
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:553)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:81)
at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:884)
at javax.activation.DataHandler.writeTo(DataHandler.java:317)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1652)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1850)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1259)
... 13 more
Caused by: javax.mail.MessagingException: Empty multipart: multipart/mixed;
boundary="----=_Part_1_1176580790.1587377502798"
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:548)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:81)
... 24 more
Code I've written to retrieve MimeMultipart from JavaMailApi's Message object to set in apache common's org.apache.commons.mail.MultiPartEmail Object using attach function.
public MimeMultipart getMimeMultipart(Message message) throws Exception {
Object content = message.getContent();
if (content instanceof String)
return null;
if (content instanceof MimeMultipart) {
MimeMultipart multiPartResult = new MimeMultipart();
MimeMultipart multiPart = (MimeMultipart) content;
List<BodyPart> result = new ArrayList<>();
for (int i = 0; i < multiPart.getCount(); i++) {
BodyPart bodyPart = (BodyPart) multiPart.getBodyPart(i);
result.addAll(getMimeMultipart(bodyPart));
}
for(BodyPart part:result) {
multiPart.addBodyPart(part);
}
return multiPartResult;
}
return null;
}
private List<BodyPart> getMimeMultipart(BodyPart part) throws Exception{
List<BodyPart> result = new ArrayList<>();
Object content = part.getContent();
if (content instanceof InputStream || content instanceof String) {
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) || StringUtils.isNotBlank(part.getFileName())) {
result.add(part);
}
return result;
}
if (content instanceof MimeMultipart) {
MimeMultipart multipart = (MimeMultipart) content;
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = (BodyPart) multipart.getBodyPart(i);
result.addAll(getMimeMultipart(bodyPart));
}
}
return result;
}
I was able to forward email excluding attachments but facing issues forwarding with attachments/inline images.
Please help me with this issue.
I'm able to forward the complete message as an attachment, how to forward the message as it is.
MultiPartEmail email = new MultiPartEmail();
MimeMultipart mp = new MimeMultipart();
MimeBodyPart fmbp = new MimeBodyPart();
fmbp.setContent(message, "message/rfc822");
fmbp.setDisposition(Part.INLINE);
mp.addBodyPart(fmbp);
email.setContent(mp);
or if I use code
MimeMultipart mp = (MimeMultipart) message.getContent();
email.setContent(mp, message.getContentType());
I'm getting forwarded email like this
screenshot of forwarded encoded mail
Here the situation is reading mail from one mail server and sending the same message to another email id, within same application.
To achieve this, I used Java Mail API for both reading and sending.
Make sure to update the properties if you're using different host for both steps.
private void sendMailJavax(Message oldMessage) {
try {
// creating a new message using the older message
MimeMessage message = new MimeMessage((MimeMessage)oldMessage);
// updating properties as per sender Mailing API
message.getSession().getProperties().clear();
message.getSession().getProperties().setProperty("mail.smtp.host", forwardHost);
// setting appropriate headers. // make sure you don't append using .add methods.
message.setFrom(new InternetAddress(emailFrom));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setReplyTo(new Address[] { new InternetAddress(replyToEmail)});
Transport.send(message);
System.out.println("Email Sent successfully....");
} catch (MessagingException mex) {
mex.printStackTrace();
}
}

HTTPClient 4.x Auth cache not set in the context

I am using HttpClient 4.5.x to call a SOAP web service with NTLM authentication.
Authentication happens successfully. It is a 3 way handshake.
For example, if i do post-request including images or other data content, then for each handshake request, the data is sent.
One recommendation from the HttpClients material online is to do a cheap request first, and use the same client context object for the subsequent big size request.
It also says this in the documentation - As of version 4.1, HttpClient automatically caches information about hosts it has successfully authenticated.
I tried the same. I have both these requests subsequently happening in the same method, and the same thread. The (default) caching does not happen. Both times the 3-way handshake was happening.
In the log I see the following statement
[org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context
May be this default does not work for NTLM.
Is there any flag to turn the caching on?
Or should I create AuthCache myself and maintain? It looks like only for preemptive authentication, one creates auth cache. So, I am doubtful if it applies to my case.
private void callServiceWithAuthentication (ByteArrayEntity entity)
{
try {
/*
AuthScope authScope = new AuthScope("WEBSERVICE-HOST", 443, AuthScope.ANY_REALM, "ntlm");
*/
CloseableHttpClient httpclient = HttpClients.createDefault();
NTCredentials ntCredentials = new NTCredentials(this.userName, this.password, null, "DOMAIN");
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, ntCredentials);
httpClientContext = HttpClientContext.create();
httpClientContext.setCredentialsProvider(credentialsProvider);
HttpHost targetHost = new HttpHost ("WEBSERVICE_HOST", 443);
// First cheap-cost request
HttpGet httpGet = new HttpGet ("WEBSERVICE_URL");
CloseableHttpResponse httpResponse = httpclient.execute(httpGet, httpClientContext);
HttpEntity getResponseEntity = httpResponse.getEntity();
// Following real costly post request
HttpPost post = new HttpPost("WEBSERVICE_URL");
post.setEntity(entity);
// Execute request
try {
CloseableHttpResponse response = httpclient.execute(post, httpClientContext);
StatusLine statusLine = response.getStatusLine();
HttpEntity rentity = response.getEntity();
System.out.println ("HTTP Response Code: " + statusLine.getStatusCode());
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
System.out.println (rentity.getContent());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
// Release current connection to the connection pool once you are done
post.releaseConnection();
}
}
catch (Exception e) {e.printStackTrace();}
finally {
}
}
I had to have the first response entity consume before the second request. Then the second request did not do the (3-way handshake) authentication again.
EntityUtils.consume(getResponseEntity);
I have more cleanup to do

MSF4J POST method receiving partial data

I'm new to MSF4J and I need to write a REST API that accepts a large XML data through POST. I am using
request.getMessegeBody()
method to get the data. I discovered that it's now deprecated but I couldn't find the newer version of it so I decided to use it anyway.
The problem is, when I send data to the microservice for the first time, it doesn't get the whole data. All the subsequent requests will get the full message body except the first.
When I try passing the request through ESB, ESB receives the whole body but when it reaches the endpoint it will be truncated.
I have also tried sending requests from different rest clients but for the first time it always gets the incomplete message body
#POST
#Consumes({ "application/xml", "application/json", "text/xml" })
#Path("test/")
public Response getReqNotification(#Context Request request) throws Exception {
Response.ResponseBuilder respBuilder =
Response.status(Response.Status.OK).entity(request);
ByteBuf b = request.getMessageBody();
byte[] bb = new byte[b.readableBytes()];
b.duplicate().readBytes(bb);
System.out.println(new String(bb));
return respBuilder.build();
}
I expect it to print the full message(which is about 2000 bytes long) every time when I send a request, but I'm only getting around 800 bytes when I first run the microservice.
I hope ill get assistance here. I have tried elsewhere but wso2 doesn't have much documentation (⌣_⌣”)
I still don't really understand what I was doing wrong but with the help of this link I have managed to come up with the following code and it works fine.
The major cha is that I now use request.getMessageContentStream() instead of the depricated request.getMessageBody()
#Consumes({ "application/xml", "application/json", "text/xml" })
#Path("test/")
public Response getReqNotification(#Context Request request) throws Exception {
Response.ResponseBuilder respBuilder =
Response.status(Response.Status.OK).entity(request);
String data = "";
BufferedInputStream bis = new BufferedInputStream(request.getMessageContentStream());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
int d;
while ((d = bis.read()) != -1) {
bos.write(d);
}
data = bos.toString();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
}
}
System.out.println(data);
//////do stuff
return respBuilder.build();
}

Apache Camel REST DSL - Validating Request Payload and return error response

I am exposing a rest service using "CamelHttpTransportServlet" that receive orders and place in jms queue. The code works fine on happy path and returns 200 response.
I have written Processor to validate the input JSON, and set http_response_code based on the input.
The issue is - for invalid requests though failure response code - 400 is set, the flow continues to the next route and pushes the data to the queue instead of sending the 400 response back to the calling app.
rest("/ordermanagement")
.post("/order").to("direct:checkInput");
from("direct:checkInput")
.process(new Processor() {
#Override
public void process(final Exchange exchange) throws Exception {
String requestBody = exchange.getIn().getBody(String.class);
if(requestBody == "" || requestBody== null) {
exchange.getIn().setBody("{ "error": Bad Request}");
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
}
}
})
.to("direct:sendToQ");
from("direct:sendToQ")
.to("jms:queue:orderReceiver")
.log("Sent to JMS");
Can someone advise what is missing here and provide a sample if possible?
Trying to implement onException approach:
rest("/ordermanagement")
.post("/order").to("direct:checkInput");
onException(CustomException.class).handled(true)
.setHeader(Exchange.HTTP_RESPONSE_CODE, code)
.setBody(jsonObject);
from("direct:checkInput")
.process(new Processor() {
#Override
public void process(final Exchange exchange) throws Exception {
String requestBody = exchange.getIn().getBody(String.class);
if(requestBody == "" || requestBody== null) {
throw CustomException(code, jsonObject)
}
}
})
.to("direct:sendToQ");
from("direct:sendToQ")
.to("jms:queue:orderReceiver")
.log("Sent to JMS");
However I could not figure out how to pass the parameters - code,jsonObject from processor to onException block.
Any help on this? Is this feasible?
I'd use something along the lines of the code example below:
onException(CustomException.class)
.handled(true)
.bean(PrepareErrorResponse.class)
.log("Error response processed");
rest("/ordermanagement")
.post("/order")
.to("direct:checkInput");
from("direct:checkInput")
.process((Exchange exchange) -> {
String requestBody = exchange.getIn().getBody(String.class);
if(requestBody == "" || requestBody== null) {
throw new CustomException(code, jsonObject);
}
})
.to("direct:sendToQ");
from("direct:sendToQ")
.to("jms:queue:orderReceiver")
.log("Sent to JMS");
Camel will store any exception caught in the exchange's property and should be therefore obtainable via the Exchange.EXCEPTION_CAUGHT property key. The sample below illustrates how such a custom error message bean can look like:
public class PrepareErrorResponse {
#Handler
public void prepareErrorResponse(Exchange exchange) {
Throwable cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
if (cause instanceof CustomException) {
CustomException validationEx = (CustomException) cause;
// ...
}
Message msg = exchange.getOut();
msg.setHeader(Exchange.CONTENT_TYPE, MediaType.APPLICATION_JSON);
msg.setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
JsonObject errorMessage = new JsonObject();
errorMessage.put("error", "Bad Request");
errorMessage.put("reason", cause.getMessage());
msg.setBody(errorMessage.toString());
// we need to do the fault=false below in order to prevent a
// HTTP 500 error code from being returned
msg.setFault(false);
}
}
Camel provides a couple of ways actually to deal with exceptions. The presented way here is just one example. The proposed code however allows to use custom redelivery strategies for different caught exceptions as well as additional stuff. If the error could get resolved within the exception handler, the route is proceeded at the point the exception occurred (i.e. temporary network issue with a redelivery strategy applied). If the error could not get fixed within the handler, the exchange will be stopped. Usually one would then send the currently processed message to a DLQ and log something about the error.
Note that this example will assume that CustomException is an unchecked exception as the processor is replaced with a simpler lambda. If you can't or don't want to use such an exception (or lambda expressions) replace the lambda-processor with new Processor() { #Override public void process(Exchange exchange) throws Exception { ... } } construct.
Here is one way to do it. You can use choice
rest("/ordermanagement")
.post("/order").to("direct:checkInput");
from("direct:checkInput")
.process(exchange -> {
String requestBody = exchange.getIn().getBody(String.class);
if(requestBody == null || requestBody.equals("")) {
exchange.getIn().setBody("{ "error": Bad Request}");
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
}
})
.choice()
.when(exchange -> {
Object header = exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE);
return header != null && header.equals(400);
})
.stop()
.otherwise()
.to("direct:sendToQ")
.endChoice();
from("direct:sendToQ")
.to("jms:queue:orderReceiver")
.log("Sent to JMS");
Setting ROUTE_STOP property to true in the processor should prevent further flow and return your response:
...
exchange.getIn().setBody("{ "error": Bad Request}");
exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
...

Mule ESB with CXF WSS4JOutInterceptor does not create a proper SOAPFault if fails

I'm using WSS4j CXF Out Interceptor in MULE to sign the SOAP response but if there is an error in this interceptor the SOAPFault is not generated properly. In fact the result is a blank body with status 200.
Problem:
If the out interceptor used to sign (WSS4JOutInterceptor) fails, it does not generates a proper SOAPFault (with status code 400/500) due to is executed in PRE_PROTOCOL and the http.status and response headers have already been written in the HttpResponse.
Cause
The SOAPFault is generated in a last phase in the interceptor chain (interceptor chain) so the HttpConnection is already open and the HttpResponse is being written, headers and status are set.
Detail
Mule version: 3.6.1 CE
CXF version: 2.5.9
WSS4j: 1.6.9
JVM: JDK7
The CXF inbound enpoint in mule calls to CxfInboundMessageProcessor. This class create the Exchange to execute the input interceptor chain , the mule flow and finally the output interceptor chain .
The most important phases that causes this error are the following:
PREPARE_SEND Opening of the connection
PRE_STREAM
PRE_PROTOCOL Misc protocol actions.->Here is executed *WSS4jOutInterceptor**
The output interceptor chain is executed in two phases, the mule interceptor MuleProtocolHeadersOutInterceptor (PRE_STREAM) pauses it. The rest of the output interceptor chain is executed when the HttpResponse is fully created.
When it is paused the execution return back to the first class CxfInboundMessageProcessor.
it is after that when the response is going to be created:
MuleMessage muleResMsg = responseEvent.getMessage();
muleResMsg.setPayload(getResponseOutputHandler(m));
The interface org.mule.api.transport.OutputHandler is used to delegate the SOAP object creation until the org.mule.transport.http.ResponseWriter is executed:
OutputHandler:
Here it can see how the method write continues with the output chain:
public void write(MuleEvent event, OutputStream out) throws IOException
{
Message outFaultMessage = m.getExchange().getOutFaultMessage();
Message outMessage = m.getExchange().getOutMessage();
Message contentMsg = null;
if (outFaultMessage != null && outFaultMessage.getContent(OutputStream.class) != null)
{
contentMsg = outFaultMessage;
}
else if (outMessage != null)
{
contentMsg = outMessage;
}
if (contentMsg == null)
{
return;
}
DelegatingOutputStream delegate = contentMsg.getContent(DelegatingOutputStream.class);
if (delegate.getOutputStream() instanceof ByteArrayOutputStream)
{
out.write(((ByteArrayOutputStream) delegate.getOutputStream()).toByteArray());
}
delegate.setOutputStream(out);
out.flush();
contentMsg.getInterceptorChain().resume();
}
org.mule.transport.http.HttpServerConnection
public void writeResponse(final HttpResponse response, Map<String,String> headers) throws IOException
{
if (response == null)
{
return;
}
if (!response.isKeepAlive())
{
Header header = new Header(HttpConstants.HEADER_CONNECTION, "close");
response.setHeader(header);
}
setKeepAlive(response.isKeepAlive());
addHeadersToHttpResponse(response, headers);
ResponseWriter writer = new ResponseWriter(this.out, encoding);
OutputStream outstream = this.out;
writer.println(response.getStatusLine());
Iterator item = response.getHeaderIterator();
while (item.hasNext())
{
Header header = (Header) item.next();
writer.print(header.toExternalForm());
}
writer.println();
writer.flush();
OutputHandler content = response.getBody();
if (content != null)
{
Header transferenc = response.getFirstHeader(HttpConstants.HEADER_TRANSFER_ENCODING);
if (transferenc != null)
{
response.removeHeaders(HttpConstants.HEADER_CONTENT_LENGTH);
if (transferenc.getValue().indexOf(HttpConstants.TRANSFER_ENCODING_CHUNKED) != -1)
{
outstream = new ChunkedOutputStream(outstream);
}
}
content.write(RequestContext.getEvent(), outstream);
if (outstream instanceof ChunkedOutputStream)
{
((ChunkedOutputStream) outstream).finish();
}
}
outstream.flush();
}
And here after httpResponse creation and set the headers is when the "body" is generated: