1 #include "http/http_request.hpp" 2 #include "multipart_parser.hpp" 3 4 #include <boost/beast/http/fields.hpp> 5 #include <boost/beast/http/message.hpp> 6 #include <boost/beast/http/string_body.hpp> 7 8 #include <memory> 9 #include <string_view> 10 #include <system_error> 11 #include <vector> 12 13 #include <gtest/gtest.h> // IWYU pragma: keep 14 15 // IWYU pragma: no_include <gtest/gtest-message.h> 16 // IWYU pragma: no_include <gtest/gtest-test-part.h> 17 // IWYU pragma: no_include "gtest/gtest_pred_impl.h" 18 // IWYU pragma: no_include <boost/beast/http/impl/fields.hpp> 19 // IWYU pragma: no_include <boost/intrusive/detail/list_iterator.hpp> 20 // IWYU pragma: no_include <boost/intrusive/detail/tree_iterator.hpp> 21 22 namespace 23 { 24 using ::testing::Test; 25 26 class MultipartTest : public Test 27 { 28 public: 29 boost::beast::http::request<boost::beast::http::string_body> req{}; 30 MultipartParser parser; 31 std::error_code ec; 32 }; 33 34 TEST_F(MultipartTest, TestGoodMultipartParser) 35 { 36 req.set("Content-Type", 37 "multipart/form-data; " 38 "boundary=---------------------------d74496d66958873e"); 39 40 req.body() = "-----------------------------d74496d66958873e\r\n" 41 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 42 "111111111111111111111111112222222222222222222222222222222\r\n" 43 "-----------------------------d74496d66958873e\r\n" 44 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 45 "{\r\n-----------------------------d74496d66958873e123456\r\n" 46 "-----------------------------d74496d66958873e\r\n" 47 "Content-Disposition: form-data; name=\"Test3\"\r\n\r\n" 48 "{\r\n--------d74496d6695887}\r\n" 49 "-----------------------------d74496d66958873e--\r\n"; 50 51 crow::Request reqIn(req, ec); 52 ParserError rc = parser.parse(reqIn); 53 ASSERT_EQ(rc, ParserError::PARSER_SUCCESS); 54 55 EXPECT_EQ(parser.boundary, 56 "\r\n-----------------------------d74496d66958873e"); 57 EXPECT_EQ(parser.mime_fields.size(), 3); 58 59 EXPECT_EQ(parser.mime_fields[0].fields.at("Content-Disposition"), 60 "form-data; name=\"Test1\""); 61 EXPECT_EQ(parser.mime_fields[0].content, 62 "111111111111111111111111112222222222222222222222222222222"); 63 64 EXPECT_EQ(parser.mime_fields[1].fields.at("Content-Disposition"), 65 "form-data; name=\"Test2\""); 66 EXPECT_EQ(parser.mime_fields[1].content, 67 "{\r\n-----------------------------d74496d66958873e123456"); 68 EXPECT_EQ(parser.mime_fields[2].fields.at("Content-Disposition"), 69 "form-data; name=\"Test3\""); 70 EXPECT_EQ(parser.mime_fields[2].content, "{\r\n--------d74496d6695887}"); 71 } 72 73 TEST_F(MultipartTest, TestBadMultipartParser1) 74 { 75 req.set("Content-Type", 76 "multipart/form-data; " 77 "boundary=---------------------------d74496d66958873e"); 78 79 req.body() = "-----------------------------d74496d66958873e\r\n" 80 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 81 "1234567890\r\n" 82 "-----------------------------d74496d66958873e\r-\r\n"; 83 84 crow::Request reqIn(req, ec); 85 ParserError rc = parser.parse(reqIn); 86 ASSERT_EQ(rc, ParserError::PARSER_SUCCESS); 87 88 EXPECT_EQ(parser.boundary, 89 "\r\n-----------------------------d74496d66958873e"); 90 EXPECT_EQ(parser.mime_fields.size(), 1); 91 } 92 93 TEST_F(MultipartTest, TestBadMultipartParser2) 94 { 95 req.set("Content-Type", 96 "multipart/form-data; " 97 "boundary=---------------------------d74496d66958873e"); 98 99 req.body() = "-----------------------------d74496d66958873e\r\n" 100 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 101 "abcd\r\n" 102 "-----------------------------d74496d66958873e-\r\n"; 103 104 crow::Request reqIn(req, ec); 105 ParserError rc = parser.parse(reqIn); 106 ASSERT_EQ(rc, ParserError::PARSER_SUCCESS); 107 108 EXPECT_EQ(parser.boundary, 109 "\r\n-----------------------------d74496d66958873e"); 110 EXPECT_EQ(parser.mime_fields.size(), 1); 111 } 112 113 TEST_F(MultipartTest, TestErrorBoundaryFormat) 114 { 115 req.set("Content-Type", 116 "multipart/form-data; " 117 "boundary+=-----------------------------d74496d66958873e"); 118 119 req.body() = "-----------------------------d74496d66958873e\r\n" 120 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 121 "{\"Key1\": 11223333333333333333333333333333333333333333}\r\n" 122 "-----------------------------d74496d66958873e\r\n" 123 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 124 "123456\r\n" 125 "-----------------------------d74496d66958873e--\r\n"; 126 127 crow::Request reqIn(req, ec); 128 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_FORMAT); 129 } 130 131 TEST_F(MultipartTest, TestErrorBoundaryCR) 132 { 133 req.set("Content-Type", 134 "multipart/form-data; " 135 "boundary=---------------------------d74496d66958873e"); 136 137 req.body() = "-----------------------------d74496d66958873e" 138 "Content-Disposition: form-data; name=\"Test1\"\r\n\r" 139 "{\"Key1\": 112233}\r\n" 140 "-----------------------------d74496d66958873e\r\n" 141 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 142 "123456\r\n" 143 "-----------------------------d74496d66958873e--\r\n"; 144 145 crow::Request reqIn(req, ec); 146 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_CR); 147 } 148 149 TEST_F(MultipartTest, TestErrorBoundaryLF) 150 { 151 req.set("Content-Type", 152 "multipart/form-data; " 153 "boundary=---------------------------d74496d66958873e"); 154 155 req.body() = "-----------------------------d74496d66958873e\r" 156 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 157 "{\"Key1\": 112233}\r\n" 158 "-----------------------------d74496d66958873e\r\n" 159 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 160 "123456\r\n" 161 "-----------------------------d74496d66958873e--\r\n"; 162 163 crow::Request reqIn(req, ec); 164 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_LF); 165 } 166 167 TEST_F(MultipartTest, TestErrorBoundaryData) 168 { 169 req.set("Content-Type", 170 "multipart/form-data; " 171 "boundary=---------------------------d7449sd6d66958873e"); 172 173 req.body() = "-----------------------------d74496d66958873e\r\n" 174 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n" 175 "{\"Key1\": 112233}\r\n" 176 "-----------------------------d74496d66958873e\r\n" 177 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 178 "123456\r\n" 179 "-----------------------------d74496d66958873e--\r\n"; 180 181 crow::Request reqIn(req, ec); 182 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_DATA); 183 } 184 185 TEST_F(MultipartTest, TestErrorEmptyHeader) 186 { 187 req.set("Content-Type", 188 "multipart/form-data; " 189 "boundary=---------------------------d74496d66958873e"); 190 191 req.body() = "-----------------------------d74496d66958873e\r\n" 192 ": form-data; name=\"Test1\"\r\n" 193 "{\"Key1\": 112233}\r\n" 194 "-----------------------------d74496d66958873e\r\n" 195 "Content-Disposition: form-data; name=\"Test2\"\r\n" 196 "123456\r\n" 197 "-----------------------------d74496d66958873e--\r\n"; 198 199 crow::Request reqIn(req, ec); 200 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_EMPTY_HEADER); 201 } 202 203 TEST_F(MultipartTest, TestErrorHeaderName) 204 { 205 req.set("Content-Type", 206 "multipart/form-data; " 207 "boundary=---------------------------d74496d66958873e"); 208 209 req.body() = "-----------------------------d74496d66958873e\r\n" 210 "Content-!!Disposition: form-data; name=\"Test1\"\r\n" 211 "{\"Key1\": 112233}\r\n" 212 "-----------------------------d74496d66958873e\r\n" 213 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 214 "123456\r\n" 215 "-----------------------------d74496d66958873e--\r\n"; 216 217 crow::Request reqIn(req, ec); 218 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_NAME); 219 } 220 221 TEST_F(MultipartTest, TestErrorHeaderValue) 222 { 223 req.set("Content-Type", 224 "multipart/form-data; " 225 "boundary=---------------------------d74496d66958873e"); 226 227 req.body() = "-----------------------------d74496d66958873e\r\n" 228 "Content-Disposition: form-data; name=\"Test1\"\r" 229 "{\"Key1\": 112233}\r\n" 230 "-----------------------------d74496d66958873e\r\n" 231 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 232 "123456\r\n" 233 "-----------------------------d74496d66958873e--\r\n"; 234 235 crow::Request reqIn(req, ec); 236 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_VALUE); 237 } 238 239 TEST_F(MultipartTest, TestErrorHeaderEnding) 240 { 241 req.set("Content-Type", 242 "multipart/form-data; " 243 "boundary=---------------------------d74496d66958873e"); 244 245 req.body() = "-----------------------------d74496d66958873e\r\n" 246 "Content-Disposition: form-data; name=\"Test1\"\r\n\r" 247 "{\"Key1\": 112233}\r\n" 248 "-----------------------------d74496d66958873e\r\n" 249 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n" 250 "123456\r\n" 251 "-----------------------------d74496d66958873e--\r\n"; 252 253 crow::Request reqIn(req, ec); 254 EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_ENDING); 255 } 256 } // namespace