Class HttpPostMultipartRequestDecoder

java.lang.Object
io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder
All Implemented Interfaces:
InterfaceHttpPostRequestDecoder

public class HttpPostMultipartRequestDecoder extends Object implements InterfaceHttpPostRequestDecoder
This decoder will decode Body and can handle POST BODY. You MUST call destroy() after completion to release all resources.
  • Field Details

    • factory

      private final HttpDataFactory factory
      Factory used to create InterfaceHttpData
    • request

      private final HttpRequest request
      Request to decode
    • maxFields

      private final int maxFields
      The maximum number of fields allows by the form
    • maxBufferedBytes

      private final int maxBufferedBytes
      The maximum number of accumulated bytes when decoding a field
    • charset

      private Charset charset
      Default charset to use
    • isLastChunk

      private boolean isLastChunk
      Does the last chunk already received
    • bodyListHttpData

      private final List<InterfaceHttpData> bodyListHttpData
      HttpDatas from Body
    • bodyMapHttpData

      private final Map<String,List<InterfaceHttpData>> bodyMapHttpData
      HttpDatas as Map from Body
    • undecodedChunk

      private ByteBuf undecodedChunk
      The current channelBuffer
    • bodyListHttpDataRank

      private int bodyListHttpDataRank
      Body HttpDatas current position
    • multipartDataBoundary

      private final String multipartDataBoundary
      If multipart, this is the boundary for the global multipart
    • multipartMixedBoundary

      private String multipartMixedBoundary
      If multipart, there could be internal multiparts (mixed) to the global multipart. Only one level is allowed.
    • currentStatus

      Current getStatus
    • currentFieldAttributes

      private Map<CharSequence,Attribute> currentFieldAttributes
      Used in Multipart
    • currentFileUpload

      private FileUpload currentFileUpload
      The current FileUpload that is currently in decode process
    • currentAttribute

      private Attribute currentAttribute
      The current Attribute that is currently in decode process
    • destroyed

      private boolean destroyed
    • discardThreshold

      private int discardThreshold
    • FILENAME_ENCODED

      private static final String FILENAME_ENCODED
  • Constructor Details

  • Method Details

    • checkDestroyed

      private void checkDestroyed()
    • isMultipart

      public boolean isMultipart()
      True if this request is a Multipart request
      Specified by:
      isMultipart in interface InterfaceHttpPostRequestDecoder
      Returns:
      True if this request is a Multipart request
    • setDiscardThreshold

      public void setDiscardThreshold(int discardThreshold)
      Set the amount of bytes after which read bytes in the buffer should be discarded. Setting this lower gives lower memory usage but with the overhead of more memory copies. Use 0 to disable it.
      Specified by:
      setDiscardThreshold in interface InterfaceHttpPostRequestDecoder
    • getDiscardThreshold

      public int getDiscardThreshold()
      Return the threshold in bytes after which read data in the buffer should be discarded.
      Specified by:
      getDiscardThreshold in interface InterfaceHttpPostRequestDecoder
    • getBodyHttpDatas

      public List<InterfaceHttpData> getBodyHttpDatas()
      This getMethod returns a List of all HttpDatas from body.
      If chunked, all chunks must have been offered using offer() getMethod. If not, NotEnoughDataDecoderException will be raised.
      Specified by:
      getBodyHttpDatas in interface InterfaceHttpPostRequestDecoder
      Returns:
      the list of HttpDatas from Body part for POST getMethod
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException - Need more chunks
    • getBodyHttpDatas

      public List<InterfaceHttpData> getBodyHttpDatas(String name)
      This getMethod returns a List of all HttpDatas with the given name from body.
      If chunked, all chunks must have been offered using offer() getMethod. If not, NotEnoughDataDecoderException will be raised.
      Specified by:
      getBodyHttpDatas in interface InterfaceHttpPostRequestDecoder
      Returns:
      All Body HttpDatas with the given name (ignore case)
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException - need more chunks
    • getBodyHttpData

      public InterfaceHttpData getBodyHttpData(String name)
      This getMethod returns the first InterfaceHttpData with the given name from body.
      If chunked, all chunks must have been offered using offer() getMethod. If not, NotEnoughDataDecoderException will be raised.
      Specified by:
      getBodyHttpData in interface InterfaceHttpPostRequestDecoder
      Returns:
      The first Body InterfaceHttpData with the given name (ignore case)
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException - need more chunks
    • offer

      Initialized the internals from a new chunk
      Specified by:
      offer in interface InterfaceHttpPostRequestDecoder
      Parameters:
      content - the new received chunk
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException - if there is a problem with the charset decoding or other errors
    • hasNext

      public boolean hasNext()
      True if at current getStatus, there is an available decoded InterfaceHttpData from the Body. This getMethod works for chunked and not chunked request.
      Specified by:
      hasNext in interface InterfaceHttpPostRequestDecoder
      Returns:
      True if at current getStatus, there is a decoded InterfaceHttpData
      Throws:
      HttpPostRequestDecoder.EndOfDataDecoderException - No more data will be available
    • next

      public InterfaceHttpData next()
      Returns the next available InterfaceHttpData or null if, at the time it is called, there is no more available InterfaceHttpData. A subsequent call to offer(httpChunk) could enable more data. Be sure to call ReferenceCounted.release() after you are done with processing to make sure to not leak any resources
      Specified by:
      next in interface InterfaceHttpPostRequestDecoder
      Returns:
      the next available InterfaceHttpData or null if none
      Throws:
      HttpPostRequestDecoder.EndOfDataDecoderException - No more data will be available
    • currentPartialHttpData

      public InterfaceHttpData currentPartialHttpData()
      Description copied from interface: InterfaceHttpPostRequestDecoder
      Returns the current InterfaceHttpData if currently in decoding status, meaning all data are not yet within, or null if there is no InterfaceHttpData currently in decoding status (either because none yet decoded or none currently partially decoded). Full decoded ones are accessible through hasNext() and next() methods.
      Specified by:
      currentPartialHttpData in interface InterfaceHttpPostRequestDecoder
      Returns:
      the current InterfaceHttpData if currently in decoding status or null if none.
    • parseBody

      private void parseBody()
      This getMethod will parse as much as possible data and fill the list and map
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException - if there is a problem with the charset decoding or other errors
    • addHttpData

      protected void addHttpData(InterfaceHttpData data)
      Utility function to add a new decoded data
    • parseBodyMultipart

      private void parseBodyMultipart()
      Parse the Body for multipart
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException - if there is a problem with the charset decoding or other errors
    • decodeMultipart

      Decode a multipart request by pieces

      NOTSTARTED PREAMBLE (
      (HEADERDELIMITER DISPOSITION (FIELD | FILEUPLOAD))*
      (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE
      (MIXEDDELIMITER MIXEDDISPOSITION MIXEDFILEUPLOAD)+
      MIXEDCLOSEDELIMITER)*
      CLOSEDELIMITER)+ EPILOGUE
      Inspired from HttpMessageDecoder
      Returns:
      the next decoded InterfaceHttpData or null if none until now.
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException - if an error occurs
    • skipControlCharacters

      private static void skipControlCharacters(ByteBuf undecodedChunk)
      Skip control Characters
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException
    • skipControlCharactersStandard

      private static void skipControlCharactersStandard(ByteBuf undecodedChunk)
    • findMultipartDelimiter

      private InterfaceHttpData findMultipartDelimiter(String delimiter, HttpPostRequestDecoder.MultiPartStatus dispositionStatus, HttpPostRequestDecoder.MultiPartStatus closeDelimiterStatus)
      Find the next Multipart Delimiter
      Parameters:
      delimiter - delimiter to find
      dispositionStatus - the next getStatus if the delimiter is a start
      closeDelimiterStatus - the next getStatus if the delimiter is a close delimiter
      Returns:
      the next InterfaceHttpData if any
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException
    • findMultipartDisposition

      private InterfaceHttpData findMultipartDisposition()
      Find the next Disposition
      Returns:
      the next InterfaceHttpData if any
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException
    • getContentDispositionAttribute

      private Attribute getContentDispositionAttribute(String... values)
    • getFileUpload

      protected InterfaceHttpData getFileUpload(String delimiter)
      Get the FileUpload (new one or current one)
      Parameters:
      delimiter - the delimiter to use
      Returns:
      the InterfaceHttpData if any
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException
    • destroy

      public void destroy()
      Destroy the HttpPostMultipartRequestDecoder and release all it resources. After this method was called it is not possible to operate on it anymore.
      Specified by:
      destroy in interface InterfaceHttpPostRequestDecoder
    • cleanFiles

      public void cleanFiles()
      Clean all HttpDatas (on Disk) for the current request.
      Specified by:
      cleanFiles in interface InterfaceHttpPostRequestDecoder
    • removeHttpDataFromClean

      public void removeHttpDataFromClean(InterfaceHttpData data)
      Remove the given FileUpload from the list of FileUploads to clean
      Specified by:
      removeHttpDataFromClean in interface InterfaceHttpPostRequestDecoder
    • cleanMixedAttributes

      private void cleanMixedAttributes()
      Remove all Attributes that should be cleaned between two FileUpload in Mixed mode
    • readLineOptimized

      private static String readLineOptimized(ByteBuf undecodedChunk, Charset charset)
      Read one line up to the CRLF or LF
      Returns:
      the String from one line
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException - Need more chunks and reset the readerIndex to the previous value
    • readDelimiterOptimized

      private static String readDelimiterOptimized(ByteBuf undecodedChunk, String delimiter, Charset charset)
      Read one line up to --delimiter or --delimiter-- and if existing the CRLF or LF Read one line up to --delimiter or --delimiter-- and if existing the CRLF or LF. Note that CRLF or LF are mandatory for opening delimiter (--delimiter) but not for closing delimiter (--delimiter--) since some clients does not include CRLF in this case.
      Parameters:
      delimiter - of the form --string, such that '--' is already included
      Returns:
      the String from one line as the delimiter searched (opening or closing)
      Throws:
      HttpPostRequestDecoder.NotEnoughDataDecoderException - Need more chunks and reset the readerIndex to the previous value
    • rewriteCurrentBuffer

      private static void rewriteCurrentBuffer(ByteBuf buffer, int lengthToSkip)
      Rewrite buffer in order to skip lengthToSkip bytes from current readerIndex, such that any readable bytes available after readerIndex + lengthToSkip (so before writerIndex) are moved at readerIndex position, therefore decreasing writerIndex of lengthToSkip at the end of the process.
      Parameters:
      buffer - the buffer to rewrite from current readerIndex
      lengthToSkip - the size to skip from readerIndex
    • loadDataMultipartOptimized

      private static boolean loadDataMultipartOptimized(ByteBuf undecodedChunk, String delimiter, HttpData httpData)
      Load the field value or file data from a Multipart request
      Returns:
      true if the last chunk is loaded (boundary delimiter found), false if need more chunks
      Throws:
      HttpPostRequestDecoder.ErrorDataDecoderException
    • cleanString

      private static String cleanString(String field)
      Clean the String from any unallowed character
      Returns:
      the cleaned String
    • skipOneLine

      private boolean skipOneLine()
      Skip one empty line
      Returns:
      True if one empty line was skipped
    • splitMultipartHeader

      private static String[] splitMultipartHeader(String sb)
      Split one header in Multipart
      Returns:
      an array of String where rank 0 is the name of the header, follows by several values that were separated by ';' or ','
    • splitMultipartHeaderValues

      private static String[] splitMultipartHeaderValues(String svalue)
      Split one header value in Multipart
      Returns:
      an array of String where values that were separated by ';' or ','
    • getCurrentAllocatedCapacity

      int getCurrentAllocatedCapacity()
      This method is package private intentionally in order to allow during tests to access to the amount of memory allocated (capacity) within the private ByteBuf undecodedChunk
      Returns:
      the number of bytes the internal buffer can contain