Class HttpPostMultipartRequestDecoder
- java.lang.Object
-
- io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder
-
- All Implemented Interfaces:
InterfaceHttpPostRequestDecoder
public class HttpPostMultipartRequestDecoder extends java.lang.Object implements InterfaceHttpPostRequestDecoder
This decoder will decode Body and can handle POST BODY. You MUST calldestroy()
after completion to release all resources.
-
-
Field Summary
Fields Modifier and Type Field Description private java.util.List<InterfaceHttpData>
bodyListHttpData
HttpDatas from Bodyprivate int
bodyListHttpDataRank
Body HttpDatas current positionprivate java.util.Map<java.lang.String,java.util.List<InterfaceHttpData>>
bodyMapHttpData
HttpDatas as Map from Bodyprivate java.nio.charset.Charset
charset
Default charset to useprivate Attribute
currentAttribute
The current Attribute that is currently in decode processprivate java.util.Map<java.lang.CharSequence,Attribute>
currentFieldAttributes
Used in Multipartprivate FileUpload
currentFileUpload
The current FileUpload that is currently in decode processprivate HttpPostRequestDecoder.MultiPartStatus
currentStatus
Current getStatusprivate boolean
destroyed
private int
discardThreshold
private HttpDataFactory
factory
Factory used to create InterfaceHttpDataprivate static java.lang.String
FILENAME_ENCODED
private boolean
isLastChunk
Does the last chunk already receivedprivate java.lang.String
multipartDataBoundary
If multipart, this is the boundary for the global multipartprivate java.lang.String
multipartMixedBoundary
If multipart, there could be internal multiparts (mixed) to the global multipart.private HttpRequest
request
Request to decodeprivate ByteBuf
undecodedChunk
The current channelBuffer
-
Constructor Summary
Constructors Constructor Description HttpPostMultipartRequestDecoder(HttpRequest request)
HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request)
HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request, java.nio.charset.Charset charset)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description protected void
addHttpData(InterfaceHttpData data)
Utility function to add a new decoded dataprivate void
checkDestroyed()
void
cleanFiles()
Clean all HttpDatas (on Disk) for the current request.private void
cleanMixedAttributes()
Remove all Attributes that should be cleaned between two FileUpload in Mixed modeprivate static java.lang.String
cleanString(java.lang.String field)
Clean the String from any unallowed characterInterfaceHttpData
currentPartialHttpData()
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).private InterfaceHttpData
decodeMultipart(HttpPostRequestDecoder.MultiPartStatus state)
Decode a multipart request by pieces
NOTSTARTED PREAMBLE (
(HEADERDELIMITER DISPOSITION (FIELD | FILEUPLOAD))*
(HEADERDELIMITER DISPOSITION MIXEDPREAMBLE
(MIXEDDELIMITER MIXEDDISPOSITION MIXEDFILEUPLOAD)+
MIXEDCLOSEDELIMITER)*
CLOSEDELIMITER)+ EPILOGUE
Inspired from HttpMessageDecodervoid
destroy()
Destroy theHttpPostMultipartRequestDecoder
and release all it resources.private InterfaceHttpData
findMultipartDelimiter(java.lang.String delimiter, HttpPostRequestDecoder.MultiPartStatus dispositionStatus, HttpPostRequestDecoder.MultiPartStatus closeDelimiterStatus)
Find the next Multipart Delimiterprivate InterfaceHttpData
findMultipartDisposition()
Find the next DispositionInterfaceHttpData
getBodyHttpData(java.lang.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.java.util.List<InterfaceHttpData>
getBodyHttpDatas()
This getMethod returns a List of all HttpDatas from body.
If chunked, all chunks must have been offered using offer() getMethod.java.util.List<InterfaceHttpData>
getBodyHttpDatas(java.lang.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.private Attribute
getContentDispositionAttribute(java.lang.String... values)
(package private) 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 undecodedChunkint
getDiscardThreshold()
Return the threshold in bytes after which read data in the buffer should be discarded.protected InterfaceHttpData
getFileUpload(java.lang.String delimiter)
Get the FileUpload (new one or current one)boolean
hasNext()
True if at current getStatus, there is an available decoded InterfaceHttpData from the Body.boolean
isMultipart()
True if this request is a Multipart requestprivate static boolean
loadDataMultipartOptimized(ByteBuf undecodedChunk, java.lang.String delimiter, HttpData httpData)
Load the field value or file data from a Multipart requestInterfaceHttpData
next()
Returns the next available InterfaceHttpData or null if, at the time it is called, there is no more available InterfaceHttpData.HttpPostMultipartRequestDecoder
offer(HttpContent content)
Initialized the internals from a new chunkprivate void
parseBody()
This getMethod will parse as much as possible data and fill the list and mapprivate void
parseBodyMultipart()
Parse the Body for multipartprivate static java.lang.String
readDelimiterOptimized(ByteBuf undecodedChunk, java.lang.String delimiter, java.nio.charset.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.private static java.lang.String
readLineOptimized(ByteBuf undecodedChunk, java.nio.charset.Charset charset)
Read one line up to the CRLF or LFvoid
removeHttpDataFromClean(InterfaceHttpData data)
Remove the given FileUpload from the list of FileUploads to cleanprivate 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.void
setDiscardThreshold(int discardThreshold)
Set the amount of bytes after which read bytes in the buffer should be discarded.private static void
skipControlCharacters(ByteBuf undecodedChunk)
Skip control Charactersprivate static void
skipControlCharactersStandard(ByteBuf undecodedChunk)
private boolean
skipOneLine()
Skip one empty lineprivate static java.lang.String[]
splitMultipartHeader(java.lang.String sb)
Split one header in Multipartprivate static java.lang.String[]
splitMultipartHeaderValues(java.lang.String svalue)
Split one header value in Multipart
-
-
-
Field Detail
-
factory
private final HttpDataFactory factory
Factory used to create InterfaceHttpData
-
request
private final HttpRequest request
Request to decode
-
charset
private java.nio.charset.Charset charset
Default charset to use
-
isLastChunk
private boolean isLastChunk
Does the last chunk already received
-
bodyListHttpData
private final java.util.List<InterfaceHttpData> bodyListHttpData
HttpDatas from Body
-
bodyMapHttpData
private final java.util.Map<java.lang.String,java.util.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 java.lang.String multipartDataBoundary
If multipart, this is the boundary for the global multipart
-
multipartMixedBoundary
private java.lang.String multipartMixedBoundary
If multipart, there could be internal multiparts (mixed) to the global multipart. Only one level is allowed.
-
currentStatus
private HttpPostRequestDecoder.MultiPartStatus currentStatus
Current getStatus
-
currentFieldAttributes
private java.util.Map<java.lang.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 java.lang.String FILENAME_ENCODED
-
-
Constructor Detail
-
HttpPostMultipartRequestDecoder
public HttpPostMultipartRequestDecoder(HttpRequest request)
- Parameters:
request
- the request to decode- Throws:
java.lang.NullPointerException
- for requestHttpPostRequestDecoder.ErrorDataDecoderException
- if the default charset was wrong when decoding or other errors
-
HttpPostMultipartRequestDecoder
public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request)
- Parameters:
factory
- the factory used to create InterfaceHttpDatarequest
- the request to decode- Throws:
java.lang.NullPointerException
- for request or factoryHttpPostRequestDecoder.ErrorDataDecoderException
- if the default charset was wrong when decoding or other errors
-
HttpPostMultipartRequestDecoder
public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request, java.nio.charset.Charset charset)
- Parameters:
factory
- the factory used to create InterfaceHttpDatarequest
- the request to decodecharset
- the charset to use as default- Throws:
java.lang.NullPointerException
- for request or charset or factoryHttpPostRequestDecoder.ErrorDataDecoderException
- if the default charset was wrong when decoding or other errors
-
-
Method Detail
-
checkDestroyed
private void checkDestroyed()
-
isMultipart
public boolean isMultipart()
True if this request is a Multipart request- Specified by:
isMultipart
in interfaceInterfaceHttpPostRequestDecoder
- 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. Use0
to disable it.- Specified by:
setDiscardThreshold
in interfaceInterfaceHttpPostRequestDecoder
-
getDiscardThreshold
public int getDiscardThreshold()
Return the threshold in bytes after which read data in the buffer should be discarded.- Specified by:
getDiscardThreshold
in interfaceInterfaceHttpPostRequestDecoder
-
getBodyHttpDatas
public java.util.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 interfaceInterfaceHttpPostRequestDecoder
- Returns:
- the list of HttpDatas from Body part for POST getMethod
- Throws:
HttpPostRequestDecoder.NotEnoughDataDecoderException
- Need more chunks
-
getBodyHttpDatas
public java.util.List<InterfaceHttpData> getBodyHttpDatas(java.lang.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 interfaceInterfaceHttpPostRequestDecoder
- Returns:
- All Body HttpDatas with the given name (ignore case)
- Throws:
HttpPostRequestDecoder.NotEnoughDataDecoderException
- need more chunks
-
getBodyHttpData
public InterfaceHttpData getBodyHttpData(java.lang.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 interfaceInterfaceHttpPostRequestDecoder
- Returns:
- The first Body InterfaceHttpData with the given name (ignore case)
- Throws:
HttpPostRequestDecoder.NotEnoughDataDecoderException
- need more chunks
-
offer
public HttpPostMultipartRequestDecoder offer(HttpContent content)
Initialized the internals from a new chunk- Specified by:
offer
in interfaceInterfaceHttpPostRequestDecoder
- 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 interfaceInterfaceHttpPostRequestDecoder
- 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 callReferenceCounted.release()
after you are done with processing to make sure to not leak any resources- Specified by:
next
in interfaceInterfaceHttpPostRequestDecoder
- 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 interfaceInterfaceHttpPostRequestDecoder
- 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
private InterfaceHttpData decodeMultipart(HttpPostRequestDecoder.MultiPartStatus state)
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
-
skipControlCharactersStandard
private static void skipControlCharactersStandard(ByteBuf undecodedChunk)
-
findMultipartDelimiter
private InterfaceHttpData findMultipartDelimiter(java.lang.String delimiter, HttpPostRequestDecoder.MultiPartStatus dispositionStatus, HttpPostRequestDecoder.MultiPartStatus closeDelimiterStatus)
Find the next Multipart Delimiter- Parameters:
delimiter
- delimiter to finddispositionStatus
- the next getStatus if the delimiter is a startcloseDelimiterStatus
- 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(java.lang.String... values)
-
getFileUpload
protected InterfaceHttpData getFileUpload(java.lang.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 theHttpPostMultipartRequestDecoder
and release all it resources. After this method was called it is not possible to operate on it anymore.- Specified by:
destroy
in interfaceInterfaceHttpPostRequestDecoder
-
cleanFiles
public void cleanFiles()
Clean all HttpDatas (on Disk) for the current request.- Specified by:
cleanFiles
in interfaceInterfaceHttpPostRequestDecoder
-
removeHttpDataFromClean
public void removeHttpDataFromClean(InterfaceHttpData data)
Remove the given FileUpload from the list of FileUploads to clean- Specified by:
removeHttpDataFromClean
in interfaceInterfaceHttpPostRequestDecoder
-
cleanMixedAttributes
private void cleanMixedAttributes()
Remove all Attributes that should be cleaned between two FileUpload in Mixed mode
-
readLineOptimized
private static java.lang.String readLineOptimized(ByteBuf undecodedChunk, java.nio.charset.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 thereaderIndex
to the previous value
-
readDelimiterOptimized
private static java.lang.String readDelimiterOptimized(ByteBuf undecodedChunk, java.lang.String delimiter, java.nio.charset.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 thereaderIndex
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 readerIndexlengthToSkip
- the size to skip from readerIndex
-
loadDataMultipartOptimized
private static boolean loadDataMultipartOptimized(ByteBuf undecodedChunk, java.lang.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 java.lang.String cleanString(java.lang.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 java.lang.String[] splitMultipartHeader(java.lang.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 java.lang.String[] splitMultipartHeaderValues(java.lang.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
-
-