Search in sources :

Example 1 with InputStreamDataSource

use of com.helger.mail.datasource.InputStreamDataSource in project as2-lib by phax.

the class HTTPHelper method readHttpRequest.

/**
 * Read headers and payload from the passed input stream provider. For large
 * file support, return {@link DataSource}. If is on, data is not read.
 *
 * @param aRDP
 *        The abstract input stream provider to use. May not be
 *        <code>null</code>.
 * @param aResponseHandler
 *        The HTTP response handler to be used. May not be <code>null</code>.
 * @param aMsg
 *        The Message to be filled. May not be <code>null</code>.
 * @param aIncomingDumper
 *        Optional incoming HTTP dumper. May be <code>null</code>.
 * @return A {@link IExtendedDataSource} that holds/refers to the body.
 * @throws IOException
 *         In case of error reading from the InputStream
 * @throws MessagingException
 *         In case header line parsing fails
 */
@Nonnull
public static IExtendedDataSource readHttpRequest(@Nonnull final IAS2HttpRequestDataProvider aRDP, @Nonnull final IAS2HttpResponseHandler aResponseHandler, @Nonnull final IMessage aMsg, @Nullable final IHTTPIncomingDumper aIncomingDumper) throws IOException, MessagingException {
    // Request method (e.g. "POST")
    aMsg.attrs().putIn(MA_HTTP_REQ_TYPE, aRDP.getHttpRequestMethod());
    // Request URL (e.g. "/as2")
    aMsg.attrs().putIn(MA_HTTP_REQ_URL, aRDP.getHttpRequestUrl());
    // HTTP version (e.g. "HTTP/1.1")
    aMsg.attrs().putIn(MA_HTTP_REQ_VERSION, aRDP.getHttpRequestVersion());
    // Get the stream to read from
    final InputStream aIS = aRDP.getHttpInputStream();
    // Parse all HTTP headers from stream
    aMsg.headers().setAllHeaders(aRDP.getHttpHeaderMap());
    // Generate DataSource
    // Put received data in a MIME body part
    final String sReceivedContentType = AS2HttpHelper.getCleanContentType(aMsg.getHeader(CHttpHeader.CONTENT_TYPE));
    final byte[] aBytePayload;
    final IExtendedDataSource aPayload;
    final String sContentLength = aMsg.getHeader(CHttpHeader.CONTENT_LENGTH);
    if (sContentLength == null) {
        // No "Content-Length" header present
        final InputStream aRealIS;
        final String sTransferEncoding = aMsg.getHeader(CHttpHeader.TRANSFER_ENCODING);
        if (sTransferEncoding != null) {
            // Remove all whitespaces in the value
            if (AS2Helper.getWithoutSpaces(sTransferEncoding).equalsIgnoreCase("chunked")) {
                // chunked encoding. Use also file backed stream as the message
                // might be large
                @WillNotClose final TempSharedFileInputStream aSharedIS = TempSharedFileInputStream.getTempSharedFileInputStream(new ChunkedInputStream(aIS), aMsg.getMessageID());
                aRealIS = aSharedIS;
                aMsg.setTempSharedFileInputStream(aSharedIS);
            } else {
                // No "Content-Length" and unsupported "Transfer-Encoding"
                sendSimpleHTTPResponse(aResponseHandler, CHttp.HTTP_LENGTH_REQUIRED);
                throw new IOException("Transfer-Encoding unimplemented: " + sTransferEncoding);
            }
        } else {
            // No "Content-Length" and no "Transfer-Encoding"
            sendSimpleHTTPResponse(aResponseHandler, CHttp.HTTP_LENGTH_REQUIRED);
            throw new IOException("Content-Length missing");
        }
        // Content-length present, or chunked encoding
        aBytePayload = null;
        aPayload = new InputStreamDataSource(aRealIS, aMsg.getAS2From() == null ? "" : aMsg.getAS2From(), sReceivedContentType, true);
    } else {
        // content-length exists
        // Read the message body - no Content-Transfer-Encoding handling
        // Retrieve the message content
        // FIXME if a value > 2GB comes in, this will fail!!
        final long nContentLength = StringParser.parseLong(sContentLength, -1);
        if (nContentLength < 0 || nContentLength > Integer.MAX_VALUE) {
            // Invalid content length (no int or too big)
            sendSimpleHTTPResponse(aResponseHandler, CHttp.HTTP_LENGTH_REQUIRED);
            throw new IOException("Content-Length '" + sContentLength + "' is invalid. Only values between 0 and " + Integer.MAX_VALUE + " are allowed.");
        }
        aBytePayload = new byte[(int) nContentLength];
        // Keeps the original InputStream open and that is okay
        try (final DataInputStream aDataIS = new DataInputStream(aIS)) {
            aDataIS.readFully(aBytePayload);
        }
        aPayload = new ByteArrayDataSource(aBytePayload, sReceivedContentType, null);
    }
    // Dump on demand
    if (aIncomingDumper != null) {
        aIncomingDumper.dumpIncomingRequest(getAllHTTPHeaderLines(aRDP.getHttpHeaderMap()), aBytePayload != null ? aBytePayload : "Payload body was not read yet, and therefore it cannot be dumped (yet) - sorry".getBytes(StandardCharsets.ISO_8859_1), aMsg);
    }
    return aPayload;
// Don't close the IS here!
}
Also used : InputStreamDataSource(com.helger.mail.datasource.InputStreamDataSource) IExtendedDataSource(com.helger.mail.datasource.IExtendedDataSource) DataInputStream(java.io.DataInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) WillNotClose(javax.annotation.WillNotClose) DataInputStream(java.io.DataInputStream) ByteArrayDataSource(com.helger.mail.datasource.ByteArrayDataSource) Nonnull(javax.annotation.Nonnull)

Aggregations

ByteArrayDataSource (com.helger.mail.datasource.ByteArrayDataSource)1 IExtendedDataSource (com.helger.mail.datasource.IExtendedDataSource)1 InputStreamDataSource (com.helger.mail.datasource.InputStreamDataSource)1 DataInputStream (java.io.DataInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 Nonnull (javax.annotation.Nonnull)1 WillNotClose (javax.annotation.WillNotClose)1