Search in sources :

Example 71 with AsyncContext

use of javax.servlet.AsyncContext in project jetty.project by eclipse.

the class ServerTimeoutsTest method testAsyncReadIdleTimeoutFires.

@Test
public void testAsyncReadIdleTimeoutFires() throws Exception {
    CountDownLatch handlerLatch = new CountDownLatch(1);
    start(new AbstractHandler() {

        @Override
        public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            baseRequest.setHandled(true);
            AsyncContext asyncContext = request.startAsync();
            asyncContext.setTimeout(0);
            ServletInputStream input = request.getInputStream();
            input.setReadListener(new ReadListener() {

                @Override
                public void onDataAvailable() throws IOException {
                    Assert.assertEquals(0, input.read());
                    Assert.assertFalse(input.isReady());
                }

                @Override
                public void onAllDataRead() throws IOException {
                }

                @Override
                public void onError(Throwable failure) {
                    if (failure instanceof TimeoutException) {
                        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
                        asyncContext.complete();
                        handlerLatch.countDown();
                    }
                }
            });
        }
    });
    long idleTimeout = 2500;
    setServerIdleTimeout(idleTimeout);
    DeferredContentProvider contentProvider = new DeferredContentProvider(ByteBuffer.allocate(1));
    CountDownLatch resultLatch = new CountDownLatch(1);
    client.POST(newURI()).content(contentProvider).send(result -> {
        if (result.getResponse().getStatus() == HttpStatus.INTERNAL_SERVER_ERROR_500)
            resultLatch.countDown();
    });
    // Async read should timeout.
    Assert.assertTrue(handlerLatch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
    // Complete the request.
    contentProvider.close();
    Assert.assertTrue(resultLatch.await(5, TimeUnit.SECONDS));
}
Also used : Request(org.eclipse.jetty.server.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) HttpServletResponse(javax.servlet.http.HttpServletResponse) AsyncContext(javax.servlet.AsyncContext) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) ReadListener(javax.servlet.ReadListener) AbstractHandler(org.eclipse.jetty.server.handler.AbstractHandler) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) ServletInputStream(javax.servlet.ServletInputStream) DeferredContentProvider(org.eclipse.jetty.client.util.DeferredContentProvider) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.Test)

Example 72 with AsyncContext

use of javax.servlet.AsyncContext in project jetty.project by eclipse.

the class SuspendHandler method handle.

@Override
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
    if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) {
        if (_read > 0) {
            byte[] buf = new byte[_read];
            request.getInputStream().read(buf);
        } else if (_read < 0) {
            InputStream in = request.getInputStream();
            int b = in.read();
            while (b != -1) b = in.read();
        }
        final AsyncContext asyncContext = baseRequest.startAsync();
        asyncContext.addListener(this);
        if (_suspendFor > 0)
            asyncContext.setTimeout(_suspendFor);
        if (_completeAfter > 0) {
            new Thread() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(_completeAfter);
                        response.getOutputStream().println("COMPLETED");
                        response.setStatus(200);
                        baseRequest.setHandled(true);
                        asyncContext.complete();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        } else if (_completeAfter == 0) {
            response.getOutputStream().println("COMPLETED");
            response.setStatus(200);
            baseRequest.setHandled(true);
            asyncContext.complete();
        }
        if (_resumeAfter > 0) {
            new Thread() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(_resumeAfter);
                        asyncContext.dispatch();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        } else if (_resumeAfter == 0) {
            asyncContext.dispatch();
        }
    } else if (request.getAttribute("TIMEOUT") != null) {
        response.setStatus(200);
        response.getOutputStream().print("TIMEOUT");
        baseRequest.setHandled(true);
    } else {
        response.setStatus(200);
        response.getOutputStream().print("RESUMED");
        baseRequest.setHandled(true);
    }
}
Also used : InputStream(java.io.InputStream) AsyncContext(javax.servlet.AsyncContext) ServletException(javax.servlet.ServletException) IOException(java.io.IOException)

Example 73 with AsyncContext

use of javax.servlet.AsyncContext in project jetty.project by eclipse.

the class StatisticsHandlerTest method testSuspendExpire.

@Test
public void testSuspendExpire() throws Exception {
    final long dispatchTime = 10;
    final long timeout = 100;
    final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>();
    final CyclicBarrier[] barrier = { new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2) };
    _statsHandler.setHandler(new AbstractHandler() {

        @Override
        public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException {
            request.setHandled(true);
            try {
                barrier[0].await();
                Thread.sleep(dispatchTime);
                if (asyncHolder.get() == null) {
                    AsyncContext async = request.startAsync();
                    asyncHolder.set(async);
                    async.setTimeout(timeout);
                }
            } catch (Exception x) {
                throw new ServletException(x);
            } finally {
                try {
                    barrier[1].await();
                } catch (Exception ignored) {
                }
            }
        }
    });
    _server.start();
    String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n";
    _connector.executeRequest(request);
    barrier[0].await();
    assertEquals(1, _statistics.getConnections());
    assertEquals(1, _statsHandler.getRequests());
    assertEquals(1, _statsHandler.getRequestsActive());
    assertEquals(1, _statsHandler.getDispatched());
    assertEquals(1, _statsHandler.getDispatchedActive());
    barrier[1].await();
    assertTrue(_latchHandler.await());
    assertNotNull(asyncHolder.get());
    asyncHolder.get().addListener(new AsyncListener() {

        @Override
        public void onTimeout(AsyncEvent event) throws IOException {
            event.getAsyncContext().complete();
        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
        }

        @Override
        public void onError(AsyncEvent event) throws IOException {
        }

        @Override
        public void onComplete(AsyncEvent event) throws IOException {
            try {
                barrier[2].await();
            } catch (Exception ignored) {
            }
        }
    });
    assertEquals(1, _statsHandler.getRequests());
    assertEquals(1, _statsHandler.getRequestsActive());
    assertEquals(1, _statsHandler.getDispatched());
    assertEquals(0, _statsHandler.getDispatchedActive());
    barrier[2].await();
    assertEquals(1, _statsHandler.getRequests());
    assertEquals(0, _statsHandler.getRequestsActive());
    assertEquals(1, _statsHandler.getDispatched());
    assertEquals(0, _statsHandler.getDispatchedActive());
    assertEquals(1, _statsHandler.getAsyncRequests());
    assertEquals(0, _statsHandler.getAsyncDispatches());
    assertEquals(1, _statsHandler.getExpires());
    assertEquals(1, _statsHandler.getResponses2xx());
    assertTrue(_statsHandler.getRequestTimeTotal() >= (timeout + dispatchTime) * 3 / 4);
    assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMax());
    assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMean(), 0.01);
    assertThat(_statsHandler.getDispatchedTimeTotal(), greaterThanOrEqualTo(dispatchTime * 3 / 4));
}
Also used : Request(org.eclipse.jetty.server.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) HttpServletResponse(javax.servlet.http.HttpServletResponse) AtomicReference(java.util.concurrent.atomic.AtomicReference) AsyncContext(javax.servlet.AsyncContext) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) CyclicBarrier(java.util.concurrent.CyclicBarrier) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) AsyncListener(javax.servlet.AsyncListener) Test(org.junit.Test)

Example 74 with AsyncContext

use of javax.servlet.AsyncContext in project jetty.project by eclipse.

the class CGI method exec.

/**
     * executes the CGI process
     *
     * @param command  the command to execute, this command is prefixed by
     *                 the context parameter "commandPrefix".
     * @param pathInfo The PATH_INFO to process,
     *                 see http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getPathInfo%28%29. Cannot be null
     * @param req the HTTP request
     * @param res the HTTP response
     * @throws IOException if the execution of the CGI process throws
     */
private void exec(File command, String pathInfo, HttpServletRequest req, HttpServletResponse res) throws IOException {
    assert req != null;
    assert res != null;
    assert pathInfo != null;
    assert command != null;
    if (LOG.isDebugEnabled()) {
        LOG.debug("CGI: script is " + command);
        LOG.debug("CGI: pathInfo is " + pathInfo);
    }
    String bodyFormEncoded = null;
    if ((HttpMethod.POST.is(req.getMethod()) || HttpMethod.PUT.is(req.getMethod())) && "application/x-www-form-urlencoded".equals(req.getContentType())) {
        MultiMap<String> parameterMap = new MultiMap<>();
        Enumeration<String> names = req.getParameterNames();
        while (names.hasMoreElements()) {
            String parameterName = names.nextElement();
            parameterMap.addValues(parameterName, req.getParameterValues(parameterName));
        }
        bodyFormEncoded = UrlEncoded.encode(parameterMap, Charset.forName(req.getCharacterEncoding()), true);
    }
    EnvList env = new EnvList(_env);
    // these ones are from "The WWW Common Gateway Interface Version 1.1"
    // look at :
    // http://Web.Golux.Com/coar/cgi/draft-coar-cgi-v11-03-clean.html#6.1.1
    env.set("AUTH_TYPE", req.getAuthType());
    int contentLen = req.getContentLength();
    if (contentLen < 0)
        contentLen = 0;
    if (bodyFormEncoded != null) {
        env.set("CONTENT_LENGTH", Integer.toString(bodyFormEncoded.length()));
    } else {
        env.set("CONTENT_LENGTH", Integer.toString(contentLen));
    }
    env.set("CONTENT_TYPE", req.getContentType());
    env.set("GATEWAY_INTERFACE", "CGI/1.1");
    if (pathInfo.length() > 0) {
        env.set("PATH_INFO", pathInfo);
    }
    String pathTranslated = req.getPathTranslated();
    if ((pathTranslated == null) || (pathTranslated.length() == 0))
        pathTranslated = pathInfo;
    env.set("PATH_TRANSLATED", pathTranslated);
    env.set("QUERY_STRING", req.getQueryString());
    env.set("REMOTE_ADDR", req.getRemoteAddr());
    env.set("REMOTE_HOST", req.getRemoteHost());
    // The identity information reported about the connection by a
    // RFC 1413 [11] request to the remote agent, if
    // available. Servers MAY choose not to support this feature, or
    // not to request the data for efficiency reasons.
    // "REMOTE_IDENT" => "NYI"
    env.set("REMOTE_USER", req.getRemoteUser());
    env.set("REQUEST_METHOD", req.getMethod());
    String scriptPath;
    String scriptName;
    // use docRoot for scriptPath, too
    if (_cgiBinProvided) {
        scriptPath = command.getAbsolutePath();
        scriptName = scriptPath.substring(_docRoot.getAbsolutePath().length());
    } else {
        String requestURI = req.getRequestURI();
        scriptName = requestURI.substring(0, requestURI.length() - pathInfo.length());
        scriptPath = getServletContext().getRealPath(scriptName);
    }
    env.set("SCRIPT_FILENAME", scriptPath);
    env.set("SCRIPT_NAME", scriptName);
    env.set("SERVER_NAME", req.getServerName());
    env.set("SERVER_PORT", Integer.toString(req.getServerPort()));
    env.set("SERVER_PROTOCOL", req.getProtocol());
    env.set("SERVER_SOFTWARE", getServletContext().getServerInfo());
    Enumeration<String> enm = req.getHeaderNames();
    while (enm.hasMoreElements()) {
        String name = enm.nextElement();
        if (name.equalsIgnoreCase("Proxy"))
            continue;
        String value = req.getHeader(name);
        env.set("HTTP_" + name.toUpperCase(Locale.ENGLISH).replace('-', '_'), value);
    }
    // these extra ones were from printenv on www.dev.nomura.co.uk
    env.set("HTTPS", (req.isSecure() ? "ON" : "OFF"));
    // "DOCUMENT_ROOT" => root + "/docs",
    // "SERVER_URL" => "NYI - http://us0245",
    // "TZ" => System.getProperty("user.timezone"),
    // are we meant to decode args here? or does the script get them
    // via PATH_INFO? if we are, they should be decoded and passed
    // into exec here...
    String absolutePath = command.getAbsolutePath();
    String execCmd = absolutePath;
    // escape the execCommand
    if (execCmd.length() > 0 && execCmd.charAt(0) != '"' && execCmd.contains(" "))
        execCmd = "\"" + execCmd + "\"";
    if (_cmdPrefix != null)
        execCmd = _cmdPrefix + " " + execCmd;
    LOG.debug("Environment: " + env.getExportString());
    LOG.debug("Command: " + execCmd);
    final Process p = Runtime.getRuntime().exec(execCmd, env.getEnvArray(), _docRoot);
    // hook processes input to browser's output (async)
    if (bodyFormEncoded != null)
        writeProcessInput(p, bodyFormEncoded);
    else if (contentLen > 0)
        writeProcessInput(p, req.getInputStream(), contentLen);
    // hook processes output to browser's input (sync)
    // if browser closes stream, we should detect it and kill process...
    OutputStream os = null;
    AsyncContext async = req.startAsync();
    try {
        async.start(new Runnable() {

            @Override
            public void run() {
                try {
                    IO.copy(p.getErrorStream(), System.err);
                } catch (IOException e) {
                    LOG.warn(e);
                }
            }
        });
        // read any headers off the top of our input stream
        // NOTE: Multiline header items not supported!
        String line = null;
        InputStream inFromCgi = p.getInputStream();
        // while ((line=br.readLine())!=null)
        while ((line = getTextLineFromStream(inFromCgi)).length() > 0) {
            if (!line.startsWith("HTTP")) {
                int k = line.indexOf(':');
                if (k > 0) {
                    String key = line.substring(0, k).trim();
                    String value = line.substring(k + 1).trim();
                    if ("Location".equals(key)) {
                        res.sendRedirect(res.encodeRedirectURL(value));
                    } else if ("Status".equals(key)) {
                        String[] token = value.split(" ");
                        int status = Integer.parseInt(token[0]);
                        res.setStatus(status);
                    } else {
                        // add remaining header items to our response header
                        res.addHeader(key, value);
                    }
                }
            }
        }
        // copy cgi content to response stream...
        os = res.getOutputStream();
        IO.copy(inFromCgi, os);
        p.waitFor();
        if (!_ignoreExitState) {
            int exitValue = p.exitValue();
            if (0 != exitValue) {
                LOG.warn("Non-zero exit status (" + exitValue + ") from CGI program: " + absolutePath);
                if (!res.isCommitted())
                    res.sendError(500, "Failed to exec CGI");
            }
        }
    } catch (IOException e) {
        // browser has probably closed its input stream - we
        // terminate and clean up...
        LOG.debug("CGI: Client closed connection!", e);
    } catch (InterruptedException ie) {
        LOG.debug("CGI: interrupted!");
    } finally {
        if (os != null) {
            try {
                os.close();
            } catch (Exception e) {
                LOG.debug(e);
            }
        }
        p.destroy();
        // LOG.debug("CGI: terminated!");
        async.complete();
    }
}
Also used : InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) AsyncContext(javax.servlet.AsyncContext) IOException(java.io.IOException) ServletException(javax.servlet.ServletException) IOException(java.io.IOException) MultiMap(org.eclipse.jetty.util.MultiMap)

Example 75 with AsyncContext

use of javax.servlet.AsyncContext in project jetty.project by eclipse.

the class SSLAsyncIOServletTest method testAsyncIOWritesWithAggregation.

@Test
public void testAsyncIOWritesWithAggregation() throws Exception {
    Random random = new Random();
    String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    final byte[] content = new byte[50000];
    for (int i = 0; i < content.length; ++i) content[i] = (byte) chars.charAt(random.nextInt(chars.length()));
    prepare(new HttpServlet() {

        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            final AsyncContext asyncContext = request.startAsync();
            asyncContext.setTimeout(0);
            final int bufferSize = 4096;
            response.setBufferSize(bufferSize);
            response.getOutputStream().setWriteListener(new WriteListener() {

                private int writes;

                private int written;

                @Override
                public void onWritePossible() throws IOException {
                    ServletOutputStream output = asyncContext.getResponse().getOutputStream();
                    do {
                        int toWrite = content.length - written;
                        if (toWrite == 0) {
                            asyncContext.complete();
                            return;
                        }
                        toWrite = Math.min(toWrite, bufferSize);
                        // trigger the condition where the bytes are aggregated.
                        if (writes == 1)
                            toWrite -= 16;
                        output.write(content, written, toWrite);
                        ++writes;
                        written += toWrite;
                    } while (output.isReady());
                }

                @Override
                public void onError(Throwable t) {
                    asyncContext.complete();
                }
            });
        }
    });
    try (Socket client = newClient()) {
        String request = "" + "GET " + contextPath + servletPath + " HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n" + "\r\n";
        OutputStream output = client.getOutputStream();
        output.write(request.getBytes("UTF-8"));
        output.flush();
        InputStream inputStream = client.getInputStream();
        HttpTester.Response response = HttpTester.parseResponse(inputStream);
        Assert.assertEquals(200, response.getStatus());
        Assert.assertArrayEquals(content, response.getContent().getBytes("UTF-8"));
    }
}
Also used : ServletOutputStream(javax.servlet.ServletOutputStream) HttpServlet(javax.servlet.http.HttpServlet) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) ServletOutputStream(javax.servlet.ServletOutputStream) HttpServletResponse(javax.servlet.http.HttpServletResponse) AsyncContext(javax.servlet.AsyncContext) IOException(java.io.IOException) HttpTester(org.eclipse.jetty.http.HttpTester) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletException(javax.servlet.ServletException) Random(java.util.Random) WriteListener(javax.servlet.WriteListener) Socket(java.net.Socket) Test(org.junit.Test)

Aggregations

AsyncContext (javax.servlet.AsyncContext)120 IOException (java.io.IOException)61 HttpServletRequest (javax.servlet.http.HttpServletRequest)53 ServletException (javax.servlet.ServletException)52 HttpServletResponse (javax.servlet.http.HttpServletResponse)50 Test (org.junit.Test)43 CountDownLatch (java.util.concurrent.CountDownLatch)33 HttpServlet (javax.servlet.http.HttpServlet)32 InterruptedIOException (java.io.InterruptedIOException)24 ServletOutputStream (javax.servlet.ServletOutputStream)20 ReadListener (javax.servlet.ReadListener)19 ServletInputStream (javax.servlet.ServletInputStream)19 AsyncEvent (javax.servlet.AsyncEvent)18 ContentResponse (org.eclipse.jetty.client.api.ContentResponse)18 AsyncListener (javax.servlet.AsyncListener)15 UncheckedIOException (java.io.UncheckedIOException)14 DeferredContentProvider (org.eclipse.jetty.client.util.DeferredContentProvider)14 Request (org.eclipse.jetty.server.Request)13 Matchers.containsString (org.hamcrest.Matchers.containsString)13 WriteListener (javax.servlet.WriteListener)11