1

I am writing a java application where I want to add events through a RESTful web service. When I try adding an event from my client application I get the following exception:

INFO: Error parsing HTTP request header
 Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the HTTP protocol
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:517)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:291)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Unknown Source)

But when I call that same URL from the browser it works if I add annotation @GET, but if I put annotation @PUT, or @POST instead of @GET I get 405 status code.I changed these annotations in the web service method. I was wondering what might be causing the issue, since it works fine from the browser but throws the exception when called from the client app.

Here is the method on the REST service:

@POST
@Path("/add/{name}/{start}/{end}/{location}/{category}/{description}") 
@Produces(MediaType.APPLICATION_JSON)
public Response addEvent(@PathParam("name") String name,@PathParam("start") String startStr,@PathParam("end") String endStr,
    @PathParam("location") String location,@PathParam("category") String category,@PathParam("description") String description) {
    System.out.println(name);
    LocalDateTime start=service.parseLocalDateTime(startStr);
    LocalDateTime end=service.parseLocalDateTime(endStr);
    Event event=new Event(name,start,end,location,category,description,false);
    if(service.addEvent(event)) {
        return Response.status(200).build();
    }
    return Response.status(500).entity("Error in event adding.").build();
}

Here is my client method:

public void addEvent(Event event) {
    String baseUrl="http://localhost:8080/InfoEvent/api/events/";
    StringBuilder sb=new StringBuilder();
    sb.append(event.getName());
    sb.append("/");
    sb.append(event.getStart());
    sb.append("/");
    sb.append(event.getEnd());
    sb.append("/");
    sb.append(event.getLocation());
    sb.append("/");
    sb.append(event.getCategory());
    sb.append("/");
    sb.append(event.getDescription());
    String parameter=sb.toString();
    String stringURL=baseUrl+"add/"+parameter;
    System.out.println(stringURL);
    try {
        URL url = new URL(stringURL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("POST");
        OutputStream os = conn.getOutputStream();
        // os.write("");
        os.flush();
        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            throw new RuntimeException("Failed-greskaa : HTTP error code : " + conn.getResponseCode());
        }
        os.close();
        conn.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
    }
}   

I also tried changing the annotations in the client method, while also changing it in the web service method, but it didn't help.

Emre Savcı
  • 3,034
  • 2
  • 16
  • 25
johnny94
  • 311
  • 4
  • 20
  • What is the return value of `event.getName()` ? Does it return "name=somethin" or just "something" ? It looks like you are missing query string on your url. – Emre Savcı Aug 29 '18 at 19:00
  • If the client is POST and the server is GET then that won't work. To avoid the 405, the client method must match the server method. What is displayed from the client code for this line: `System.out.println(stringURL);`? Is it encoded? – Andrew S Aug 29 '18 at 19:06
  • @EmreSavcı it return just "something".. – johnny94 Aug 29 '18 at 19:15
  • @AndrewS Example od that out is: http://localhost:8080/InfoEvent/api/events/add/Concert/2018-01-01T01:01/2018-12-31T22:22/London/Concert/This%20is%20description Client method match server metod. – johnny94 Aug 29 '18 at 19:17
  • 1
    What is the full URL string? Are there spaces or other special characters? The browser might be encoding it. – Andrew S Aug 29 '18 at 19:30
  • @Andrew S There are spaces in description: "This is description" . I will try now without spaces.. – johnny94 Aug 29 '18 at 19:51
  • 1
    Is there any reason you can't use a high level HTTP client library like Spring Web (RestTemplate), Square OkHttp, Apache HttpComponents, etc? They will hide most of the details of working with the HTTP protocol. If that's not possible, it looks like you have a space in the URL (`/This is description`), which is not valid. – Mike Aug 29 '18 at 19:59
  • @Andrew S Thank you.. It was about spaces... – johnny94 Aug 29 '18 at 21:07
  • Why are you sending all this data in the URL? You should be sending all this data in the request body as JSON. – Paul Samsotha Aug 30 '18 at 02:14
  • @Paul Samsotha I tried with JSON, but on service side i had exception with parsing LocalDateTime.. – johnny94 Aug 30 '18 at 09:05
  • @johnny94 So, that's not a reason to stop. There are solutions to that. – Paul Samsotha Aug 30 '18 at 09:58

1 Answers1

0

I don't have the reputation to comment,

Since the exception says 'Error parsing HTTP header' and 'invalid character in HTTP protocol', it looks like the server did not understand the request.

Answers in here suggest it may have to do with HTTPS vs HTTP. java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens.

bnu
  • 1