Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Jetty 9 bug

That SHOULD is for the existence of the header as a whole, name + value as a header that exists in the list of headers on a request.

Since the topic is about a Request Header with a name and no value, we have to then rely on the
ABNF (Augmented Backus-Naur Form) notation that says 1* for the value.

User-Agent     = "User-Agent" ":" 1*( product | comment )

--
Joakim Erdfelt <joakim@xxxxxxxxxxx>
Developer advice, services and support
from the Jetty & CometD experts


On Fri, May 24, 2013 at 1:20 PM, Elrod, David <elrodd@xxxxxxxxxxxxx> wrote:
The reference to RFC2616 states "User agents SHOULD include this
[User-Agent] field with requests."

RFC 2119 specifies:

3. SHOULD    This word, or the adjective "RECOMMENDED", mean that there
    may exist valid reasons in particular circumstances to ignore a
    particular item, but the full implications must be understood and
    carefully weighed before choosing a different course.


Has there been a decision to upgrade "SHOULD" requirements to "MUST" for
other fields as well?

David



From: jetty-users-bounces@xxxxxxxxxxx [jetty-users-bounces@xxxxxxxxxxx] on behalf of Joakim Erdfelt [joakim@xxxxxxxxxxx]
Sent: Friday, May 24, 2013 11:04
To: JETTY user mailing list
Subject: Re: [jetty-users] Jetty 9 bug

Per RFC2616 (The HTTP/1.1 spec)

You are required to provide a value, otherwise the header is deemed invalid.

In your example request headers, jetty parses the User-Agent header, sees no valid, deems it to be bad, and excludes it from the header map.
Jetty has a philosophy of being tolerant on what it can accept, and strict on what it generates.
If we didn't have this philosophy, your bad header would result in an error 400 (Bad Request).

The fact that Jetty 8 gave you a blank is that Jetty 8 had the bug of keeping a reference to a bad header.
The Jetty 8 behavior is at best, undefined. 

With the common http handling introduced in Jetty 9 (for HTTP 1.0, HTTP 1.1, SPDY, and HTTP 2.0) many of these kinds of undefined behavior have been addressed.

Sorry :(


--
Joakim Erdfelt <joakim@xxxxxxxxxxx>
Developer advice, services and support
from the Jetty & CometD experts


On Fri, May 24, 2013 at 10:30 AM, Denis Bardadym <bardadymchik@xxxxxxxxx> wrote:
Hello.

I found that jetty 9.0.2.v20130417 HttpServletRequest.getHeader return null when header is empty. You can see this in simple application:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;

public class MinimalServlets {

    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        ServletHandler handler = new ServletHandler();
        server.setHandler(handler);
        handler.addServletWithMapping(HelloServlet.class, "/*");
        server.start();
        server.join();
    }

    public static class HelloServlet extends HttpServlet {

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            response.setStatus(HttpServletResponse.SC_OK);
            java.io.Writer w = response.getWriter();
            w.println(request.getHeader("User-Agent"));
            w.println(request.getHeader("X-Not-Exists"));
        }
    }
}

When i send curl request like this:

mac:liftweb den$ curl -v -D - -H "User-Agent;" -H "User-Agent:" http://localhost:8080
* About to connect() to localhost port 8080 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> Accept: */*
> User-Agent:
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/html; charset=ISO-8859-1
Content-Type: text/html; charset=ISO-8859-1
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
< Server: Jetty(9.0.2.v20130417)
Server: Jetty(9.0.2.v20130417)

<
null
null
* Connection #0 to host localhost left intact
* Closing connection #0

It returns both nulls. But by javadoc it should return null only if header not presented but you see that User-Agent: just empty.

This does not happen in jetty8:

@SuppressWarnings("serial")
public class HelloServlet extends HttpServlet
{
    String greeting = "Hello";

    public HelloServlet()
    {
    }

    public HelloServlet(String hi)
    {
        greeting = hi;
    }

    private String getVal(String s) {
        if(s == null) return "null";
        else return s;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        response.setContentType("text/html");
        response.setStatus(HttpServletResponse.SC_OK);
        PrintWriter writer = response.getWriter();
        writer.println("User-Agent: " + getVal(request.getHeader("User-Agent")));
        writer.println("X-Not-Exists: " + getVal(request.getHeader("X-Not-Exists")));
        writer.flush();
        writer.close();
    }
}

and
public class OneServletContext {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);

        // Server content from tmp
        ServletHolder holder = context.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/tmp/*");
        holder.setInitParameter("resourceBase", "/tmp");
        holder.setInitParameter("pathInfoOnly", "true");

        // Serve some hello world servlets
        context.addServlet(new ServletHolder(new HelloServlet()), "/*");
        context.addServlet(new ServletHolder(new HelloServlet("Buongiorno Mondo")), "/it/*");
        context.addServlet(new ServletHolder(new HelloServlet("Bonjour le Monde")), "/fr/*");

        server.start();
        server.join();
    }
}

so when i send it request:

mac:liftweb den$ curl -v -D - -H "User-Agent;" -H "User-Agent:" http://localhost:8080
* About to connect() to localhost port 8080 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> Accept: */*
> User-Agent:
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/html;charset=ISO-8859-1
Content-Type: text/html;charset=ISO-8859-1
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
< Server: Jetty(8.1.10.v20130312)
Server: Jetty(8.1.10.v20130312)

<
User-Agent:
X-Not-Exists: null
* Connection #0 to host localhost left intact
* Closing connection #0


Does it really bug??

Thanks, Denis Bardadym.


_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/jetty-users


_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/jetty-users



Back to the top