@@ -49,11 +49,15 @@ public async Task ReadFormAsync_SimpleData_ReturnsParsedFormCollection(bool buff
4949
5050 private const string MultipartContentType = "multipart/form-data; boundary=WebKitFormBoundary5pDRpGheQXaM8k3T" ;
5151
52+ private const string MultipartContentTypeWithSpecialCharacters = "multipart/form-data; boundary=\" WebKitFormBoundary/:5pDRpGheQXaM8k3T\" " ;
53+
5254 private const string EmptyMultipartForm = "--WebKitFormBoundary5pDRpGheQXaM8k3T--" ;
5355
5456 // Note that CRLF (\r\n) is required. You can't use multi-line C# strings here because the line breaks on Linux are just LF.
5557 private const string MultipartFormEnd = "--WebKitFormBoundary5pDRpGheQXaM8k3T--\r \n " ;
5658
59+ private const string MultipartFormEndWithSpecialCharacters = "--WebKitFormBoundary/:5pDRpGheQXaM8k3T--\r \n " ;
60+
5761 private const string MultipartFormField = "--WebKitFormBoundary5pDRpGheQXaM8k3T\r \n " +
5862"Content-Disposition: form-data; name=\" description\" \r \n " +
5963"\r \n " +
@@ -71,6 +75,12 @@ public async Task ReadFormAsync_SimpleData_ReturnsParsedFormCollection(bool buff
7175"\r \n " +
7276"<html><body>Hello World</body></html>\r \n " ;
7377
78+ private const string MultipartFormFileSpecialCharacters = "--WebKitFormBoundary/:5pDRpGheQXaM8k3T\r \n " +
79+ "Content-Disposition: form-data; name=\" description\" \r \n " +
80+ "\r \n " +
81+ "Foo\r \n " ;
82+
83+
7484 private const string MultipartFormWithField =
7585 MultipartFormField +
7686 MultipartFormEnd ;
@@ -88,6 +98,10 @@ public async Task ReadFormAsync_SimpleData_ReturnsParsedFormCollection(bool buff
8898 MultipartFormEncodedFilename +
8999 MultipartFormEnd ;
90100
101+ private const string MultipartFormWithSpecialCharacters =
102+ MultipartFormFileSpecialCharacters +
103+ MultipartFormEndWithSpecialCharacters ;
104+
91105 [ Theory ]
92106 [ InlineData ( true ) ]
93107 [ InlineData ( false ) ]
@@ -208,6 +222,43 @@ public async Task ReadFormAsync_MultipartWithFile_ReturnsParsedFormCollection(bo
208222 await responseFeature . CompleteAsync ( ) ;
209223 }
210224
225+ [ Theory ]
226+ [ InlineData ( true ) ]
227+ [ InlineData ( false ) ]
228+ public async Task ReadFormAsync_MultipartWithFileAndQuotedBoundaryString_ReturnsParsedFormCollection ( bool bufferRequest )
229+ {
230+ var formContent = Encoding . UTF8 . GetBytes ( MultipartFormWithSpecialCharacters ) ;
231+ var context = new DefaultHttpContext ( ) ;
232+ var responseFeature = new FakeResponseFeature ( ) ;
233+ context . Features . Set < IHttpResponseFeature > ( responseFeature ) ;
234+ context . Request . ContentType = MultipartContentTypeWithSpecialCharacters ;
235+ context . Request . Body = new NonSeekableReadStream ( formContent ) ;
236+
237+ IFormFeature formFeature = new FormFeature ( context . Request , new FormOptions ( ) { BufferBody = bufferRequest } ) ;
238+ context . Features . Set < IFormFeature > ( formFeature ) ;
239+
240+ var formCollection = context . Request . Form ;
241+
242+ Assert . NotNull ( formCollection ) ;
243+
244+ // Cached
245+ formFeature = context . Features . Get < IFormFeature > ( ) ;
246+ Assert . NotNull ( formFeature ) ;
247+ Assert . NotNull ( formFeature . Form ) ;
248+ Assert . Same ( formCollection , formFeature . Form ) ;
249+ Assert . Same ( formCollection , await context . Request . ReadFormAsync ( ) ) ;
250+
251+ // Content
252+ Assert . Equal ( 1 , formCollection . Count ) ;
253+ Assert . Equal ( "Foo" , formCollection [ "description" ] ) ;
254+
255+ Assert . NotNull ( formCollection . Files ) ;
256+ Assert . Equal ( 0 , formCollection . Files . Count ) ;
257+
258+ // Cleanup
259+ await responseFeature . CompleteAsync ( ) ;
260+ }
261+
211262 [ Theory ]
212263 [ InlineData ( true ) ]
213264 [ InlineData ( false ) ]
0 commit comments