Search in sources :

Example 1 with MultiPartIllegalFormatException

use of com.linkedin.multipart.exceptions.MultiPartIllegalFormatException in project rest.li by linkedin.

the class TestMIMEReaderExceptions method missingContentTypeHeader.

// These tests all verify that we throw the correct exception in the face of RFC violating bodies:
@Test
public void missingContentTypeHeader() {
    StreamRequest streamRequest = null;
    try {
        streamRequest = mock(StreamRequest.class);
        when(streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn(null);
        MultiPartMIMEReader.createAndAcquireStream(streamRequest);
        Assert.fail();
    } catch (MultiPartIllegalFormatException illegalMimeFormatException) {
        Assert.assertEquals(illegalMimeFormatException.getMessage(), "Malformed multipart mime request. No Content-Type header in this request");
        verify(streamRequest, times(1)).getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER);
    }
}
Also used : MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) Test(org.testng.annotations.Test)

Example 2 with MultiPartIllegalFormatException

use of com.linkedin.multipart.exceptions.MultiPartIllegalFormatException in project rest.li by linkedin.

the class MultiPartMIMEUtils method extractBoundary.

static String extractBoundary(final String contentTypeHeader) throws MultiPartIllegalFormatException {
    if (!contentTypeHeader.toLowerCase().startsWith(MultiPartMIMEUtils.MULTIPART_PREFIX)) {
        throw new MultiPartIllegalFormatException("Malformed multipart mime request. Not a valid multipart mime header.");
    }
    if (!contentTypeHeader.contains(";")) {
        throw new MultiPartIllegalFormatException("Malformed multipart mime request. Improperly formatted Content-Type header. " + "Expected at least one parameter in addition to the content type.");
    }
    final String[] contentTypeParameters = contentTypeHeader.split(";");
    // In case someone used something like bOuNdArY
    final Map<String, String> parameterMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
    for (final String parameter : contentTypeParameters) {
        // We don't need the first bit here.
        if (parameter.startsWith(MULTIPART_PREFIX)) {
            continue;
        }
        final String trimmedParameter = parameter.trim();
        // According to the RFC, there could be an '=' character in the boundary so we can't just split on =.
        // We find the first equals and then go from there. It should also be noted that the RFC does allow
        // boundaries to start and end with quotes.
        final int firstEquals = trimmedParameter.indexOf("=");
        // equals is the last character.
        if (firstEquals == 0 || firstEquals == -1 || firstEquals == trimmedParameter.length() - 1) {
            throw new MultiPartIllegalFormatException("Invalid parameter format.");
        }
        final String parameterKey = trimmedParameter.substring(0, firstEquals);
        String parameterValue = trimmedParameter.substring(firstEquals + 1, trimmedParameter.length());
        if (parameterValue.charAt(0) == '"') {
            if (parameterValue.charAt(parameterValue.length() - 1) != '"') {
                throw new MultiPartIllegalFormatException("Invalid parameter format.");
            }
            // Remove the leading and trailing '"'
            parameterValue = parameterValue.substring(1, parameterValue.length() - 1);
        }
        // there are multiple boundary parameters.
        if (parameterMap.containsKey(parameterKey)) {
            throw new MultiPartIllegalFormatException("Invalid parameter format. Multiple declarations of the same parameter!");
        }
        parameterMap.put(parameterKey, parameterValue);
    }
    final String boundaryValue = parameterMap.get(BOUNDARY_PARAMETER);
    if (boundaryValue == null) {
        throw new MultiPartIllegalFormatException("No boundary parameter found!");
    }
    return boundaryValue;
}
Also used : MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) ByteString(com.linkedin.data.ByteString) TreeMap(java.util.TreeMap)

Example 3 with MultiPartIllegalFormatException

use of com.linkedin.multipart.exceptions.MultiPartIllegalFormatException in project rest.li by linkedin.

the class TestMIMEReaderExceptions method invalidContentType.

@Test
public void invalidContentType() throws Exception {
    StreamRequest streamRequest = null;
    try {
        streamRequest = mock(StreamRequest.class);
        when(streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn("Some erroneous content type");
        MultiPartMIMEReader.createAndAcquireStream(streamRequest);
        Assert.fail();
    } catch (MultiPartIllegalFormatException illegalMimeFormatException) {
        Assert.assertEquals(illegalMimeFormatException.getMessage(), "Malformed multipart mime request. Not a valid multipart mime header.");
        verify(streamRequest, times(1)).getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER);
    }
}
Also used : MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) Test(org.testng.annotations.Test)

Example 4 with MultiPartIllegalFormatException

use of com.linkedin.multipart.exceptions.MultiPartIllegalFormatException in project rest.li by linkedin.

the class TestMIMEReaderExceptions method executeRequestWithDesiredException.

// /////////////////////////////////////////////////////////////////////////////////////
private void executeRequestWithDesiredException(final ByteString requestPayload, final int chunkSize, final String contentTypeHeader, final String desiredExceptionMessage) throws Exception {
    mockR2AndWrite(requestPayload, chunkSize, contentTypeHeader);
    final CountDownLatch latch = new CountDownLatch(1);
    MultiPartMIMEReader reader = MultiPartMIMEReader.createAndAcquireStream(_streamRequest);
    _currentMultiPartMIMEReaderCallback = new MultiPartMIMEExceptionReaderCallbackImpl(latch, reader);
    reader.registerReaderCallback(_currentMultiPartMIMEReaderCallback);
    latch.await(_testTimeout, TimeUnit.MILLISECONDS);
    // Verify the correct exception was sent to the reader callback. The test itself will then verify
    // if the correct error (if applicable) was sent to the single part reader callback.
    Assert.assertTrue(_currentMultiPartMIMEReaderCallback.getStreamError() instanceof MultiPartIllegalFormatException);
    Assert.assertEquals(_currentMultiPartMIMEReaderCallback.getStreamError().getMessage(), desiredExceptionMessage);
    // Verify these are unusable.
    try {
        reader.drainAllParts();
        Assert.fail();
    } catch (MultiPartReaderFinishedException multiPartReaderFinishedException) {
    // pass
    }
    // Unnecessary to verify how many times requestData on the read handle was called.
    verify(_readHandle, atLeastOnce()).request(isA(Integer.class));
    verify(_readHandle, times(1)).cancel();
    verify(_streamRequest, times(1)).getEntityStream();
    verify(_streamRequest, times(1)).getHeader(MIMETestUtils.HEADER_CONTENT_TYPE);
    verify(_entityStream, times(1)).setReader(isA(MultiPartMIMEReader.R2MultiPartMIMEReader.class));
    verifyNoMoreInteractions(_streamRequest);
    verifyNoMoreInteractions(_entityStream);
}
Also used : MultiPartReaderFinishedException(com.linkedin.multipart.exceptions.MultiPartReaderFinishedException) MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 5 with MultiPartIllegalFormatException

use of com.linkedin.multipart.exceptions.MultiPartIllegalFormatException in project rest.li by linkedin.

the class TestMIMEReaderExceptions method payloadMissingFinalBoundary.

@Test(dataProvider = "multiplePartsDataSource")
public void payloadMissingFinalBoundary(final int chunkSize, final List<MimeBodyPart> bodyPartList) throws Exception {
    MimeMultipart multiPartMimeBody = new MimeMultipart();
    // Add your body parts
    for (final MimeBodyPart bodyPart : bodyPartList) {
        multiPartMimeBody.addBodyPart(bodyPart);
    }
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    multiPartMimeBody.writeTo(byteArrayOutputStream);
    final byte[] mimePayload = byteArrayOutputStream.toByteArray();
    // To simulate the missing boundary, we have to trim 3 bytes off of the end. We need to snip the very last 2 bytes
    // because javax mail places a CRLF at the very end (which is not needed) and then another byte before that (which is a
    // hyphen) so that the final boundary never occurs.
    final byte[] trimmedMimePayload = Arrays.copyOf(mimePayload, mimePayload.length - 3);
    final ByteString requestPayload = ByteString.copy(trimmedMimePayload);
    executeRequestWithDesiredException(requestPayload, chunkSize, multiPartMimeBody.getContentType(), "Malformed multipart mime request. Finishing boundary missing!");
    List<SinglePartMIMEExceptionReaderCallbackImpl> singlePartMIMEReaderCallbacks = _currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks();
    Assert.assertEquals(singlePartMIMEReaderCallbacks.size(), multiPartMimeBody.getCount());
    // The last one should have gotten a stream error
    for (int i = 0; i < singlePartMIMEReaderCallbacks.size() - 1; i++) {
        // Actual
        final SinglePartMIMEExceptionReaderCallbackImpl currentCallback = singlePartMIMEReaderCallbacks.get(i);
        // Expected
        final BodyPart currentExpectedPart = multiPartMimeBody.getBodyPart(i);
        // Construct expected headers and verify they match
        final Map<String, String> expectedHeaders = new HashMap<>();
        @SuppressWarnings("unchecked") final Enumeration<Header> allHeaders = currentExpectedPart.getAllHeaders();
        while (allHeaders.hasMoreElements()) {
            final Header header = allHeaders.nextElement();
            expectedHeaders.put(header.getName(), header.getValue());
        }
        Assert.assertEquals(currentCallback.getHeaders(), expectedHeaders);
        // Verify the body matches
        Assert.assertNotNull(currentCallback.getFinishedData());
        if (currentExpectedPart.getContent() instanceof byte[]) {
            Assert.assertEquals(currentCallback.getFinishedData().copyBytes(), currentExpectedPart.getContent());
        } else {
            // Default is String
            Assert.assertEquals(new String(currentCallback.getFinishedData().copyBytes()), currentExpectedPart.getContent());
        }
    }
    SinglePartMIMEExceptionReaderCallbackImpl singlePartMIMEExceptionReaderCallback = singlePartMIMEReaderCallbacks.get(singlePartMIMEReaderCallbacks.size() - 1);
    Assert.assertNull(singlePartMIMEExceptionReaderCallback.getFinishedData());
    Assert.assertTrue(singlePartMIMEExceptionReaderCallback.getStreamError() instanceof MultiPartIllegalFormatException);
    try {
        singlePartMIMEExceptionReaderCallback.getSinglePartMIMEReader().requestPartData();
        Assert.fail();
    } catch (SinglePartFinishedException singlePartFinishedException) {
    // pass
    }
}
Also used : MimeBodyPart(javax.mail.internet.MimeBodyPart) BodyPart(javax.mail.BodyPart) HashMap(java.util.HashMap) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteString(com.linkedin.data.ByteString) SinglePartFinishedException(com.linkedin.multipart.exceptions.SinglePartFinishedException) Header(javax.mail.Header) MimeMultipart(javax.mail.internet.MimeMultipart) MultiPartIllegalFormatException(com.linkedin.multipart.exceptions.MultiPartIllegalFormatException) MimeBodyPart(javax.mail.internet.MimeBodyPart) Test(org.testng.annotations.Test)

Aggregations

MultiPartIllegalFormatException (com.linkedin.multipart.exceptions.MultiPartIllegalFormatException)5 Test (org.testng.annotations.Test)3 ByteString (com.linkedin.data.ByteString)2 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)2 MultiPartReaderFinishedException (com.linkedin.multipart.exceptions.MultiPartReaderFinishedException)1 SinglePartFinishedException (com.linkedin.multipart.exceptions.SinglePartFinishedException)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 HashMap (java.util.HashMap)1 TreeMap (java.util.TreeMap)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 BodyPart (javax.mail.BodyPart)1 Header (javax.mail.Header)1 MimeBodyPart (javax.mail.internet.MimeBodyPart)1 MimeMultipart (javax.mail.internet.MimeMultipart)1