I am writing a personal web server.
When I send the GET request to the system, the system responds well.
But when I send the HEAD request, I get the following problems:
sun.net.httpserver.ExchangeImpl sendResponseHeaders
WARNING: sendResponseHeaders: being invoked with a content length for a HEAD
request java.io.IOException: response headers not sent yet at
jdk.httpserver/sun.net.httpserver.PlaceholderOutputStream.checkWrap(ExchangeImpl.java:448)
at
jdk.httpserver/sun.net.httpserver.PlaceholderOutputStream.write(ExchangeImpl.java:458)
at
ir.utux.service.HandleHttpResponse.writeResponse(HandleHttpResponse.java:32)
This is the code I wrote to manage the response, to simplify HEAD and GET together.
public void writeResponse(SettingModal settingModal) {
try {
switch (requestHeader.getMethod()) {
case HEAD,GET -> {
response.getResponseHeaders().set("Server", "utux HttpServer");
response.getResponseHeaders().set("Connection", "close");
response.getResponseHeaders().set("Transfer-encoding", "chunked");
response.getResponseHeaders().set("Content-Type", ContentType.HTML);
response.sendResponseHeaders(HttpStatus.SC_OK, "".length());
response.getResponseBody().write("".getBytes(StandardCharsets.UTF_8));
response.getResponseBody().flush();
response.getResponseBody().close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
I found the problem
BODY should not be sent in response to HEAD requests.
Related
I want to use Java Http Client: java.net.http.HttpClient in asynchronous way.
When I receive http response (any http code) or timeout I want to execute some custom Java code. I struggle to complete the body of error handling.
CompletableFuture<HttpResponse<String>> response =
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApplyAsync(body -> {
System.out.println("Request finished");
return body;
})
.exceptionallyAsync(exception -> {
// WHAT TO RETURN HERE ?
});
The method: exceptionallyAsync returns: CompletableFuture<T>, but I do not know how to complete this method.
Can you please help me to finish this method? I cannot find example in GitHub or Google.
You can use
.exceptionally(this::handlError)
If this is your response handler with a method like:
private Void handlError(Throwable ex) {
System.out.println(ex.toString());
return null;
}
I wrote the following code:
public static void handleRequest(HttpServerRequest request, Vertx vertx) throws FileNotFoundException {
if (request.method() == HttpMethod.GET) {
if (request.path().equals("/healthcheck")) {
returnResponse(request, "I'm alive!!!\n", true);
System.out.println("OK");
return;
}
...
}
returnResponse(request, "Not Valid Request", false);
System.out.println("This request cannot be handled");
}
The weird part is that once I get a GET request with path "/healthcheck", I get in console both:
OK
and
This request cannot be handled
I'd expect to get only "OK", and then the method has to return.
Do you know how to make it happen?
You may be getting more than one request and one of them is not a get request. Can you monitor the server by inserting Log Statements
I finally found out that my browser does send two requests.
The first request is the GET localhost:8080/healthcheck and the second one is GET localhost:8080/favicon.
GET localhost:8080/favicon doesn't satisfy the condition, and the code prints "This request cannot be handled".
You are trying to handle a Preflighted request.
According to MDN
Preflighted requests unlike simple requests (discussed above),
"preflighted" requests first send an HTTP OPTIONS request header to
the resource on the other domain, in order to determine whether the
actual request is safe to send. Cross-site requests are preflighted
like this since they may have implications to user data
try this instead
public static void handleRequest(HttpServerRequest request, Vertx vertx) throws FileNotFoundException {
if(request.method() == HttpMethod.OPTIONS) {
return;
}
if (request.method() == HttpMethod.GET) {
if (request.path().equals("/healthcheck")) {
returnResponse(request, "I'm alive!!!\n", true);
System.out.println("OK");
return;
}
...
}
returnResponse(request, "Not Valid Request", false);
System.out.println("This request cannot be handled");
}
I'm using ResteasyClient to make a REST client to my another service A. Say, service A throws an exception CustomException with a message : Got Invalid request.
Here is how I am using the Client:
public Response callServiceA(final String query) {
ResteasyClient client = new ResteasyClientBuilder().build();
String link = "abc.com/serviceA";
ResteasyWebTarget target = client.target(link).path("call");
Form form = new Form();
form.param("query", query);
Response response;
try {
String data =
target.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
response = Response.ok().entity(data).build();
} catch (Exception e) {
String message = e.getMessage();
e.printStackTrace();
response = Response.serverError().entity(e.getMessage()).build();
} finally{
client.close();
}
return response;
}
However, when I print the stacktrace, I'm unable to find my custom error message. I can just see the message as HTTP 400 Bad Request.
Could you please suggest me how to access the error message?
NOTE: I am able to get the error message when I call the serviceA using the restClient. Hence, I dont think there is an issue with the service.
Don't deserialize the response straight to a String.
String data = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE),
String.class);
When you do this (and there is a problem), you just get a client side exception, which doesn't carry information about the response. Instead just get the Response with the overloaded post method
Response response = ...
.post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED_TYPE));
Then you can get details from the Response, like the status and such. You can get the body with response.readEntity(String.class). This way you don't need to handle any exceptions. Just handle conditions based on the status.
Do note though that the Response above is an inbound Response, which is different from the outbound Response in your current code. So just make sure not to try and send out an inbound Response.
Also see this answer and it's comments for some design ideas.
I'm working on a rest API where when post request is made by posting an XML file it should send the response 200 OK if the file is received successfully and 400 if the XML file is having any tag missing and 500 error if GET is used instead of POST. I am able to do the first two cases 200 and 400, not sure how to add 500 in the code. Am posting my code here, please suggest.
if (dataFile==null) {
try {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
"Failed to process content of file.");
}
catch (IOException e1) {
LOGGER.error("Failed to send response due to error:
" + e1.getMessage());
}
}
else{
response.setStatus(HttpServletResponse.SC_OK);
response.addHeader("Location", getResourceUri(dataFileMetadata,
request).toString());
It's pretty unclear from your code example what you're trying to do there,
but I would guess that you're talking about something like this:
#POST
#Path("/some/path")
#Consumes(MediaType.APPLICATION_XML)
public Response post(String someXML) {
try {
if (isMissingTag(someXML)) {
return Response.status(Status.BAD_REQUEST).entity("error message goes here").build();
}
// do stuff
return Response.ok().build();
} catch (Exception e) {
LOG.error("error message goes here", e);
return Response.serverError().entity("error message goes here").build();
}
}
You won't need to return anything if someone tries to hit your service with a GET, since you aren't publishing that as an endpoint in the first place.
I would highly suggest reading the jersey user guide if you're interested in writing restful web services.
I am thinking of how to make AJAX take use of servlet 3 async response. in the request-response synchronize processing model, when the response comes back, the callback of XmlHttpRequest can get the response text; but how about the response is processed in another thread, and returns some message, what will the XHR get when the request ends? can it still get the response body? I tried a simple codes to test it, it seems failed to get the response;
I can understand this, when the AJAX request return, there is nothing in the response, it will be delayed in another server thread, so the callback get nothing.
But I wonder is there any way to let AJAX get the correct response?
I am afraid I made a mistake before, that I forget to call asycContext.complete() after the async processing is done. after complete() is called, ajax get the response. However, if the processing lasts longer than the timeout setting, just like following, a exception saying illegal state of the asynccontext will arise, and client get nothing:
final AsyncContext ac = request.startAsync();
ac.setTimeout(1000);
Executors.newSingleThreadExecutor().execute(new Runnable(){
#Override
public void run() {
PrintWriter pw;
try {
Thread.sleep(2000);
pw = ac.getResponse().getWriter();
pw.write("Hello, World!");
ac.complete();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
So I guess the keys here are: 1. call complete after processing is done; 2. set a appropriate timeout;