Search in sources :

Example 6 with ServletOutputStream

use of jakarta.servlet.ServletOutputStream in project spring-framework by spring-projects.

the class ServletServerHttpResponse method writeToOutputStream.

/**
 * Write the DataBuffer to the response body OutputStream.
 * Invoked only when {@link ServletOutputStream#isReady()} returns "true"
 * and the readable bytes in the DataBuffer is greater than 0.
 * @return the number of bytes written
 */
protected int writeToOutputStream(DataBuffer dataBuffer) throws IOException {
    ServletOutputStream outputStream = this.outputStream;
    InputStream input = dataBuffer.asInputStream();
    int bytesWritten = 0;
    byte[] buffer = new byte[this.bufferSize];
    int bytesRead;
    while (outputStream.isReady() && (bytesRead = input.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
        bytesWritten += bytesRead;
    }
    return bytesWritten;
}
Also used : ServletOutputStream(jakarta.servlet.ServletOutputStream) InputStream(java.io.InputStream)

Example 7 with ServletOutputStream

use of jakarta.servlet.ServletOutputStream in project spring-framework by spring-projects.

the class ServletServerHttpResponse method flush.

private void flush() throws IOException {
    ServletOutputStream outputStream = this.outputStream;
    if (outputStream.isReady()) {
        try {
            outputStream.flush();
            this.flushOnNext = false;
        } catch (IOException ex) {
            this.flushOnNext = true;
            throw ex;
        }
    } else {
        this.flushOnNext = true;
    }
}
Also used : ServletOutputStream(jakarta.servlet.ServletOutputStream) IOException(java.io.IOException)

Example 8 with ServletOutputStream

use of jakarta.servlet.ServletOutputStream in project tomcat by apache.

the class ApplicationDispatcher method doForward.

private void doForward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
    // Reset any output that has been buffered, but keep headers/cookies
    if (response.isCommitted()) {
        throw new IllegalStateException(sm.getString("applicationDispatcher.forward.ise"));
    }
    try {
        response.resetBuffer();
    } catch (IllegalStateException e) {
        throw e;
    }
    // Set up to handle the specified request and response
    State state = new State(request, response, false);
    if (context.getDispatcherWrapsSameObject()) {
        // Check SRV.9.2 / RequestDispacther Javadoc
        checkSameObjects(request, response);
    }
    wrapResponse(state);
    // Handle an HTTP named dispatcher forward
    if ((servletPath == null) && (pathInfo == null)) {
        ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
        HttpServletRequest hrequest = state.hrequest;
        wrequest.setRequestURI(hrequest.getRequestURI());
        wrequest.setContextPath(hrequest.getContextPath());
        wrequest.setServletPath(hrequest.getServletPath());
        wrequest.setPathInfo(hrequest.getPathInfo());
        wrequest.setQueryString(hrequest.getQueryString());
        processRequest(request, response, state);
    } else // Handle an HTTP path-based forward
    {
        ApplicationHttpRequest wrequest = (ApplicationHttpRequest) wrapRequest(state);
        HttpServletRequest hrequest = state.hrequest;
        if (hrequest.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) == null) {
            wrequest.setAttribute(RequestDispatcher.FORWARD_REQUEST_URI, hrequest.getRequestURI());
            wrequest.setAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH, hrequest.getContextPath());
            wrequest.setAttribute(RequestDispatcher.FORWARD_SERVLET_PATH, hrequest.getServletPath());
            wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO, hrequest.getPathInfo());
            wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING, hrequest.getQueryString());
            wrequest.setAttribute(RequestDispatcher.FORWARD_MAPPING, hrequest.getHttpServletMapping());
        }
        wrequest.setContextPath(context.getEncodedPath());
        wrequest.setRequestURI(requestURI);
        wrequest.setServletPath(servletPath);
        wrequest.setPathInfo(pathInfo);
        if (queryString != null) {
            wrequest.setQueryString(queryString);
            wrequest.setQueryParams(queryString);
        }
        wrequest.setMapping(mapping);
        processRequest(request, response, state);
    }
    if (request.isAsyncStarted()) {
        // response as it may be written to during the async handling
        return;
    }
    // This is not a real close in order to support error processing
    if (wrapper.getLogger().isDebugEnabled()) {
        wrapper.getLogger().debug(" Disabling the response for further output");
    }
    if (response instanceof ResponseFacade) {
        ((ResponseFacade) response).finish();
    } else {
        // and may no longer be instance of RequestFacade
        if (wrapper.getLogger().isDebugEnabled()) {
            wrapper.getLogger().debug(" The Response is vehiculed using a wrapper: " + response.getClass().getName());
        }
        // Close anyway
        try {
            PrintWriter writer = response.getWriter();
            writer.close();
        } catch (IllegalStateException e) {
            try {
                ServletOutputStream stream = response.getOutputStream();
                stream.close();
            } catch (IllegalStateException | IOException f) {
            // Ignore
            }
        } catch (IOException e) {
        // Ignore
        }
    }
}
Also used : HttpServletRequest(jakarta.servlet.http.HttpServletRequest) ServletOutputStream(jakarta.servlet.ServletOutputStream) ResponseFacade(org.apache.catalina.connector.ResponseFacade) IOException(java.io.IOException) PrintWriter(java.io.PrintWriter)

Example 9 with ServletOutputStream

use of jakarta.servlet.ServletOutputStream in project tomcat by apache.

the class DefaultServlet method serveResource.

/**
 * Serve the specified resource, optionally including the data content.
 *
 * @param request       The servlet request we are processing
 * @param response      The servlet response we are creating
 * @param content       Should the content be included?
 * @param inputEncoding The encoding to use if it is necessary to access the
 *                      source as characters rather than as bytes
 *
 * @exception IOException if an input/output error occurs
 * @exception ServletException if a servlet-specified error occurs
 */
protected void serveResource(HttpServletRequest request, HttpServletResponse response, boolean content, String inputEncoding) throws IOException, ServletException {
    boolean serveContent = content;
    // Identify the requested resource path
    String path = getRelativePath(request, true);
    if (debug > 0) {
        if (serveContent) {
            log("DefaultServlet.serveResource:  Serving resource '" + path + "' headers and data");
        } else {
            log("DefaultServlet.serveResource:  Serving resource '" + path + "' headers only");
        }
    }
    if (path.length() == 0) {
        // Context root redirect
        doDirectoryRedirect(request, response);
        return;
    }
    WebResource resource = resources.getResource(path);
    boolean isError = DispatcherType.ERROR == request.getDispatcherType();
    if (!resource.exists()) {
        // Check if we're included so we can return the appropriate
        // missing resource name in the error
        String requestUri = (String) request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
        if (requestUri == null) {
            requestUri = request.getRequestURI();
        } else {
            // SRV.9.3 says we must throw a FNFE
            throw new FileNotFoundException(sm.getString("defaultServlet.missingResource", requestUri));
        }
        if (isError) {
            response.sendError(((Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)).intValue());
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("defaultServlet.missingResource", requestUri));
        }
        return;
    }
    if (!resource.canRead()) {
        // Check if we're included so we can return the appropriate
        // missing resource name in the error
        String requestUri = (String) request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
        if (requestUri == null) {
            requestUri = request.getRequestURI();
        } else {
            // reasonable
            throw new FileNotFoundException(sm.getString("defaultServlet.missingResource", requestUri));
        }
        if (isError) {
            response.sendError(((Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)).intValue());
        } else {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, requestUri);
        }
        return;
    }
    boolean included = false;
    // satisfied.
    if (resource.isFile()) {
        // Checking If headers
        included = (request.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH) != null);
        if (!included && !isError && !checkIfHeaders(request, response, resource)) {
            return;
        }
    }
    // Find content type.
    String contentType = resource.getMimeType();
    if (contentType == null) {
        contentType = getServletContext().getMimeType(resource.getName());
        resource.setMimeType(contentType);
    }
    // These need to reflect the original resource, not the potentially
    // precompressed version of the resource so get them now if they are going to
    // be needed later
    String eTag = null;
    String lastModifiedHttp = null;
    if (resource.isFile() && !isError) {
        eTag = generateETag(resource);
        lastModifiedHttp = resource.getLastModifiedHttp();
    }
    // Serve a precompressed version of the file if present
    boolean usingPrecompressedVersion = false;
    if (compressionFormats.length > 0 && !included && resource.isFile() && !pathEndsWithCompressedExtension(path)) {
        List<PrecompressedResource> precompressedResources = getAvailablePrecompressedResources(path);
        if (!precompressedResources.isEmpty()) {
            ResponseUtil.addVaryFieldName(response, "accept-encoding");
            PrecompressedResource bestResource = getBestPrecompressedResource(request, precompressedResources);
            if (bestResource != null) {
                response.addHeader("Content-Encoding", bestResource.format.encoding);
                resource = bestResource.resource;
                usingPrecompressedVersion = true;
            }
        }
    }
    Ranges ranges = FULL;
    long contentLength = -1L;
    if (resource.isDirectory()) {
        if (!path.endsWith("/")) {
            doDirectoryRedirect(request, response);
            return;
        }
        // suppress them
        if (!listings) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("defaultServlet.missingResource", request.getRequestURI()));
            return;
        }
        contentType = "text/html;charset=UTF-8";
    } else {
        if (!isError) {
            if (useAcceptRanges) {
                // Accept ranges header
                response.setHeader("Accept-Ranges", "bytes");
            }
            // Parse range specifier
            ranges = parseRange(request, response, resource);
            if (ranges == null) {
                return;
            }
            // ETag header
            response.setHeader("ETag", eTag);
            // Last-Modified header
            response.setHeader("Last-Modified", lastModifiedHttp);
        }
        // Get content length
        contentLength = resource.getContentLength();
        // (silent) ISE when setting the output buffer size
        if (contentLength == 0L) {
            serveContent = false;
        }
    }
    ServletOutputStream ostream = null;
    PrintWriter writer = null;
    if (serveContent) {
        // Trying to retrieve the servlet output stream
        try {
            ostream = response.getOutputStream();
        } catch (IllegalStateException e) {
            // trying to serve a text file
            if (!usingPrecompressedVersion && isText(contentType)) {
                writer = response.getWriter();
                // Cannot reliably serve partial content with a Writer
                ranges = FULL;
            } else {
                throw e;
            }
        }
    }
    // Check to see if a Filter, Valve or wrapper has written some content.
    // If it has, disable range requests and setting of a content length
    // since neither can be done reliably.
    ServletResponse r = response;
    long contentWritten = 0;
    while (r instanceof ServletResponseWrapper) {
        r = ((ServletResponseWrapper) r).getResponse();
    }
    if (r instanceof ResponseFacade) {
        contentWritten = ((ResponseFacade) r).getContentWritten();
    }
    if (contentWritten > 0) {
        ranges = FULL;
    }
    String outputEncoding = response.getCharacterEncoding();
    Charset charset = B2CConverter.getCharset(outputEncoding);
    boolean conversionRequired;
    /*
         * The test below deliberately uses != to compare two Strings. This is
         * because the code is looking to see if the default character encoding
         * has been returned because no explicit character encoding has been
         * defined. There is no clean way of doing this via the Servlet API. It
         * would be possible to add a Tomcat specific API but that would require
         * quite a bit of code to get to the Tomcat specific request object that
         * may have been wrapped. The != test is a (slightly hacky) quick way of
         * doing this.
         */
    boolean outputEncodingSpecified = outputEncoding != org.apache.coyote.Constants.DEFAULT_BODY_CHARSET.name() && outputEncoding != resources.getContext().getResponseCharacterEncoding();
    if (!usingPrecompressedVersion && isText(contentType) && outputEncodingSpecified && !charset.equals(fileEncodingCharset)) {
        conversionRequired = true;
        // Conversion often results fewer/more/different bytes.
        // That does not play nicely with range requests.
        ranges = FULL;
    } else {
        conversionRequired = false;
    }
    if (resource.isDirectory() || isError || ranges == FULL) {
        // Set the appropriate output headers
        if (contentType != null) {
            if (debug > 0) {
                log("DefaultServlet.serveFile:  contentType='" + contentType + "'");
            }
            // Don't override a previously set content type
            if (response.getContentType() == null) {
                response.setContentType(contentType);
            }
        }
        if (resource.isFile() && contentLength >= 0 && (!serveContent || ostream != null)) {
            if (debug > 0) {
                log("DefaultServlet.serveFile:  contentLength=" + contentLength);
            }
            // written to the response or if conversion will be taking place
            if (contentWritten == 0 && !conversionRequired) {
                response.setContentLengthLong(contentLength);
            }
        }
        if (serveContent) {
            try {
                response.setBufferSize(output);
            } catch (IllegalStateException e) {
            // Silent catch
            }
            InputStream renderResult = null;
            if (ostream == null) {
                // content directly.
                if (resource.isDirectory()) {
                    renderResult = render(request, getPathPrefix(request), resource, inputEncoding);
                } else {
                    renderResult = resource.getInputStream();
                    if (included) {
                        // Need to make sure any BOM is removed
                        if (!renderResult.markSupported()) {
                            renderResult = new BufferedInputStream(renderResult);
                        }
                        Charset bomCharset = processBom(renderResult, useBomIfPresent.stripBom);
                        if (bomCharset != null && useBomIfPresent.useBomEncoding) {
                            inputEncoding = bomCharset.name();
                        }
                    }
                }
                copy(renderResult, writer, inputEncoding);
            } else {
                // Output is via an OutputStream
                if (resource.isDirectory()) {
                    renderResult = render(request, getPathPrefix(request), resource, inputEncoding);
                } else {
                    // Check to see if conversion is required
                    if (conversionRequired || included) {
                        // When including a file, we need to check for a BOM
                        // to determine if a conversion is required, so we
                        // might as well always convert
                        InputStream source = resource.getInputStream();
                        if (!source.markSupported()) {
                            source = new BufferedInputStream(source);
                        }
                        Charset bomCharset = processBom(source, useBomIfPresent.stripBom);
                        if (bomCharset != null && useBomIfPresent.useBomEncoding) {
                            inputEncoding = bomCharset.name();
                        }
                        // specified
                        if (outputEncodingSpecified) {
                            OutputStreamWriter osw = new OutputStreamWriter(ostream, charset);
                            PrintWriter pw = new PrintWriter(osw);
                            copy(source, pw, inputEncoding);
                            pw.flush();
                        } else {
                            // Just included but no conversion
                            renderResult = source;
                        }
                    } else {
                        if (!checkSendfile(request, response, resource, contentLength, null)) {
                            // sendfile not possible so check if resource
                            // content is available directly via
                            // CachedResource. Do not want to call
                            // getContent() on other resource
                            // implementations as that could trigger loading
                            // the contents of a very large file into memory
                            byte[] resourceBody = null;
                            if (resource instanceof CachedResource) {
                                resourceBody = resource.getContent();
                            }
                            if (resourceBody == null) {
                                // Resource content not directly available,
                                // use InputStream
                                renderResult = resource.getInputStream();
                            } else {
                                // Use the resource content directly
                                ostream.write(resourceBody);
                            }
                        }
                    }
                }
                // the output (this method closes the stream)
                if (renderResult != null) {
                    copy(renderResult, ostream);
                }
            }
        }
    } else {
        if ((ranges == null) || (ranges.getEntries().isEmpty())) {
            return;
        }
        // Partial content response.
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        if (ranges.getEntries().size() == 1) {
            Ranges.Entry range = ranges.getEntries().get(0);
            long start = getStart(range, contentLength);
            long end = getEnd(range, contentLength);
            response.addHeader("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
            long length = end - start + 1;
            response.setContentLengthLong(length);
            if (contentType != null) {
                if (debug > 0) {
                    log("DefaultServlet.serveFile:  contentType='" + contentType + "'");
                }
                response.setContentType(contentType);
            }
            if (serveContent) {
                try {
                    response.setBufferSize(output);
                } catch (IllegalStateException e) {
                // Silent catch
                }
                if (ostream != null) {
                    if (!checkSendfile(request, response, resource, contentLength, range)) {
                        copy(resource, contentLength, ostream, range);
                    }
                } else {
                    // we should not get here
                    throw new IllegalStateException();
                }
            }
        } else {
            response.setContentType("multipart/byteranges; boundary=" + mimeSeparation);
            if (serveContent) {
                try {
                    response.setBufferSize(output);
                } catch (IllegalStateException e) {
                // Silent catch
                }
                if (ostream != null) {
                    copy(resource, contentLength, ostream, ranges, contentType);
                } else {
                    // we should not get here
                    throw new IllegalStateException();
                }
            }
        }
    }
}
Also used : Ranges(org.apache.tomcat.util.http.parser.Ranges) ServletResponse(jakarta.servlet.ServletResponse) HttpServletResponse(jakarta.servlet.http.HttpServletResponse) ServletOutputStream(jakarta.servlet.ServletOutputStream) BufferedInputStream(java.io.BufferedInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) FileNotFoundException(java.io.FileNotFoundException) WebResource(org.apache.catalina.WebResource) Charset(java.nio.charset.Charset) BufferedInputStream(java.io.BufferedInputStream) ResponseFacade(org.apache.catalina.connector.ResponseFacade) CachedResource(org.apache.catalina.webresources.CachedResource) OutputStreamWriter(java.io.OutputStreamWriter) ServletResponseWrapper(jakarta.servlet.ServletResponseWrapper) PrintWriter(java.io.PrintWriter)

Example 10 with ServletOutputStream

use of jakarta.servlet.ServletOutputStream in project tomcat by apache.

the class CompressionFilterTestServlet method doGet.

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletOutputStream out = response.getOutputStream();
    response.setContentType("text/plain");
    Enumeration<String> e = request.getHeaders("Accept-Encoding");
    while (e.hasMoreElements()) {
        String name = e.nextElement();
        out.println(name);
        if (name.indexOf("gzip") != -1) {
            out.println("gzip supported -- able to compress");
        } else {
            out.println("gzip not supported");
        }
    }
    out.println("Compression Filter Test Servlet");
    out.println("Minimum content length for compression is 128 bytes");
    out.println("**********  32 bytes  **********");
    out.println("**********  32 bytes  **********");
    out.println("**********  32 bytes  **********");
    out.println("**********  32 bytes  **********");
    out.close();
}
Also used : ServletOutputStream(jakarta.servlet.ServletOutputStream)

Aggregations

ServletOutputStream (jakarta.servlet.ServletOutputStream)13 HttpServletResponse (jakarta.servlet.http.HttpServletResponse)5 IOException (java.io.IOException)3 Test (org.junit.jupiter.api.Test)3 ServletResponse (jakarta.servlet.ServletResponse)2 InputStream (java.io.InputStream)2 OutputStreamWriter (java.io.OutputStreamWriter)2 PrintWriter (java.io.PrintWriter)2 ResponseFacade (org.apache.catalina.connector.ResponseFacade)2 MockHttpServletRequest (org.springframework.mock.web.MockHttpServletRequest)2 MockHttpServletResponse (org.springframework.mock.web.MockHttpServletResponse)2 WireFeedOutput (com.rometools.rome.io.WireFeedOutput)1 ServletResponseWrapper (jakarta.servlet.ServletResponseWrapper)1 WriteListener (jakarta.servlet.WriteListener)1 HttpServletRequest (jakarta.servlet.http.HttpServletRequest)1 BufferedInputStream (java.io.BufferedInputStream)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 FileInputStream (java.io.FileInputStream)1 FileNotFoundException (java.io.FileNotFoundException)1