16
16
17
17
package org .springframework .integration .http .dsl ;
18
18
19
+ import static org .assertj .core .api .Assertions .assertThat ;
19
20
import static org .springframework .security .test .web .servlet .request .SecurityMockMvcRequestPostProcessors .httpBasic ;
20
21
import static org .springframework .security .test .web .servlet .setup .SecurityMockMvcConfigurers .springSecurity ;
21
22
import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .get ;
23
+ import static org .springframework .test .web .servlet .request .MockMvcRequestBuilders .multipart ;
22
24
import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .content ;
23
25
import static org .springframework .test .web .servlet .result .MockMvcResultMatchers .status ;
24
26
25
27
import java .nio .charset .Charset ;
28
+ import java .nio .charset .StandardCharsets ;
26
29
import java .util .Collections ;
27
30
import java .util .List ;
31
+ import java .util .Map ;
28
32
29
33
import org .junit .Before ;
30
34
import org .junit .Test ;
31
35
import org .junit .runner .RunWith ;
32
36
33
37
import org .springframework .beans .factory .annotation .Autowired ;
38
+ import org .springframework .beans .factory .annotation .Qualifier ;
34
39
import org .springframework .context .annotation .Bean ;
35
40
import org .springframework .context .annotation .Configuration ;
41
+ import org .springframework .http .MediaType ;
36
42
import org .springframework .http .ResponseEntity ;
37
43
import org .springframework .http .client .ClientHttpRequestFactory ;
38
44
import org .springframework .http .client .ClientHttpResponse ;
41
47
import org .springframework .integration .dsl .IntegrationFlow ;
42
48
import org .springframework .integration .dsl .IntegrationFlows ;
43
49
import org .springframework .integration .dsl .context .IntegrationFlowContext ;
50
+ import org .springframework .integration .http .multipart .UploadedMultipartFile ;
44
51
import org .springframework .integration .http .outbound .HttpRequestExecutingMessageHandler ;
45
52
import org .springframework .integration .security .channel .ChannelSecurityInterceptor ;
46
53
import org .springframework .integration .security .channel .SecuredChannel ;
54
+ import org .springframework .messaging .Message ;
47
55
import org .springframework .messaging .MessageChannel ;
56
+ import org .springframework .messaging .PollableChannel ;
57
+ import org .springframework .mock .web .MockPart ;
48
58
import org .springframework .security .access .AccessDecisionManager ;
49
59
import org .springframework .security .access .vote .AffirmativeBased ;
50
60
import org .springframework .security .access .vote .RoleVoter ;
64
74
import org .springframework .web .client .DefaultResponseErrorHandler ;
65
75
import org .springframework .web .client .HttpClientErrorException ;
66
76
import org .springframework .web .context .WebApplicationContext ;
77
+ import org .springframework .web .multipart .MultipartResolver ;
78
+ import org .springframework .web .multipart .support .StandardServletMultipartResolver ;
79
+ import org .springframework .web .servlet .DispatcherServlet ;
67
80
68
81
/**
69
82
* @author Artem Bilan
@@ -107,20 +120,14 @@ public void testHttpProxyFlow() throws Exception {
107
120
get ("/service" )
108
121
.with (httpBasic ("admin" , "admin" ))
109
122
.param ("name" , "foo" ))
110
- .andExpect (
111
- content ()
112
- .string ("FOO" ));
123
+ .andExpect (content ().string ("FOO" ));
113
124
114
125
this .mockMvc .perform (
115
126
get ("/service" )
116
127
.with (httpBasic ("user" , "user" ))
117
128
.param ("name" , "name" ))
118
- .andExpect (
119
- status ()
120
- .isForbidden ())
121
- .andExpect (
122
- content ()
123
- .string ("Error" ));
129
+ .andExpect (status ().isForbidden ())
130
+ .andExpect (content ().string ("Error" ));
124
131
}
125
132
126
133
@ Test
@@ -137,21 +144,59 @@ public void testDynamicHttpEndpoint() throws Exception {
137
144
138
145
this .mockMvc .perform (
139
146
get ("/dynamic" )
140
- .with (httpBasic ("admin " , "admin " ))
147
+ .with (httpBasic ("user " , "user " ))
141
148
.param ("name" , "BAR" ))
142
- .andExpect (
143
- content ()
144
- .string ("bar" ));
149
+ .andExpect (content ().string ("bar" ));
145
150
146
151
flowRegistration .destroy ();
147
152
148
153
this .mockMvc .perform (
149
154
get ("/dynamic" )
150
- .with (httpBasic ("admin " , "admin " ))
155
+ .with (httpBasic ("user " , "user " ))
151
156
.param ("name" , "BAZ" ))
152
- .andExpect (
153
- status ()
154
- .isNotFound ());
157
+ .andExpect (status ().isNotFound ());
158
+ }
159
+
160
+ @ Autowired
161
+ @ Qualifier ("multiPartFilesChannel" )
162
+ private PollableChannel multiPartFilesChannel ;
163
+
164
+ @ Test
165
+ @ SuppressWarnings ("unchecked" )
166
+ public void testMultiPartFiles () throws Exception {
167
+ MockPart mockPart1 = new MockPart ("a1" , "file1" , "ABC" .getBytes (StandardCharsets .UTF_8 ));
168
+ mockPart1 .getHeaders ().setContentType (MediaType .TEXT_PLAIN );
169
+ MockPart mockPart2 = new MockPart ("a1" , "file2" , "DEF" .getBytes (StandardCharsets .UTF_8 ));
170
+ mockPart2 .getHeaders ().setContentType (MediaType .TEXT_PLAIN );
171
+ this .mockMvc .perform (
172
+ multipart ("/multiPartFiles" )
173
+ .part (mockPart1 , mockPart2 )
174
+ .with (httpBasic ("user" , "user" )))
175
+ .andExpect (status ().isOk ());
176
+
177
+ Message <?> result = this .multiPartFilesChannel .receive (10_000 );
178
+
179
+ assertThat (result )
180
+ .isNotNull ()
181
+ .extracting (Message ::getPayload )
182
+ .satisfies ((payload ) ->
183
+ assertThat ((Map <String , ?>) payload )
184
+ .hasSize (1 )
185
+ .extracting ((map ) -> map .get ("a1" ))
186
+ .asList ()
187
+ .hasSize (2 )
188
+ .satisfies ((list ) -> {
189
+ assertThat (list )
190
+ .element (0 )
191
+ .extracting ((file ) ->
192
+ ((UploadedMultipartFile ) file ).getOriginalFilename ())
193
+ .isEqualTo ("file1" );
194
+ assertThat (list )
195
+ .element (1 )
196
+ .extracting ((file ) ->
197
+ ((UploadedMultipartFile ) file ).getOriginalFilename ())
198
+ .isEqualTo ("file2" );
199
+ }));
155
200
}
156
201
157
202
@ Configuration
@@ -237,6 +282,19 @@ public IntegrationFlow httpProxyErrorFlow() {
237
282
new ResponseEntity <>(p .getResponseBodyAsString (), p .getStatusCode ()));
238
283
}
239
284
285
+ @ Bean
286
+ public IntegrationFlow multiPartFilesFlow () {
287
+ return IntegrationFlows
288
+ .from (Http .inboundChannelAdapter ("/multiPartFiles" ))
289
+ .channel ((c ) -> c .queue ("multiPartFilesChannel" ))
290
+ .get ();
291
+ }
292
+
293
+ @ Bean (name = DispatcherServlet .MULTIPART_RESOLVER_BEAN_NAME )
294
+ public MultipartResolver multipartResolver () {
295
+ return new StandardServletMultipartResolver ();
296
+ }
297
+
240
298
@ Bean
241
299
public AccessDecisionManager accessDecisionManager () {
242
300
return new AffirmativeBased (Collections .singletonList (new RoleVoter ()));
0 commit comments