1 package de.juplo.httpresources;
2
3
4 import static org.assertj.core.api.Assertions.*;
5 import static org.mockserver.verify.VerificationTimes.exactly;
6
7 import static org.mockserver.model.HttpRequest.request;
8 import org.junit.jupiter.api.BeforeEach;
9 import org.junit.jupiter.api.Test;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.beans.factory.annotation.Value;
14 import org.springframework.boot.autoconfigure.SpringBootApplication;
15 import org.springframework.boot.test.context.SpringBootTest;
16 import org.springframework.cache.Cache;
17 import org.springframework.core.io.Resource;
18 import org.springframework.util.MimeType;
19
20 import java.time.*;
21
22
23
24
25
26
27 @SpringBootTest
28 public class HttpResourcesIT extends IntegrationTestBase
29 {
30 private final static Logger LOG =
31 LoggerFactory.getLogger(HttpResourcesIT.class);
32
33
34 @Autowired
35 HttpResources resources;
36 @Autowired
37 Cache cache;
38
39 @Value("classpath:remote/remote.html")
40 Resource remote;
41 @Value("classpath:remote/modified.html")
42 Resource modified;
43
44
45 @BeforeEach
46 public void clearCache()
47 {
48 cache.clear();
49 }
50
51
52 @Test
53 public void testFetchExistent() throws Exception
54 {
55 LOG.info("<-- Start of test-case");
56
57 HttpResource resource = resources.getResource(address("/remote.html"));
58
59 assertThat(resource.exists()).isTrue();
60 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
61 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
62 server.verify(FETCH("/remote.html"), exactly(1));
63 }
64
65 @Test
66 public void testFetchNonExistent() throws Exception
67 {
68 LOG.info("<-- Start of test-case");
69
70 HttpResource resource = resources.getResource(address("/peter.html"));
71
72 assertThat(resource.exists()).isFalse();
73 server.verify(FETCH("/peter.html"), exactly(2));
74 }
75
76 @Test
77 public void testFetchServerResponse500() throws Exception
78 {
79 LOG.info("<-- Start of test-case");
80
81 server.when(FETCH("/peter.html")).respond(INTERNAL_SERVER_ERROR());
82
83 HttpResource resource = resources.getResource(address("/peter.html"));
84
85 assertThat(resource.exists()).isFalse();
86 server.verify(FETCH("/peter.html"), exactly(2));
87 }
88
89 @Test
90 public void testCaching() throws Exception
91 {
92 LOG.info("<-- Start of test-case");
93
94 String uri = address("/remote.html");
95
96 HttpResource resource;
97
98 LOG.debug("First access to {}", uri);
99 resource= resources.getResource(uri);
100 assertThat(resource.exists()).isTrue();
101 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
102 assertThat(resource.isModified()).isFalse();
103 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
104
105 LOG.debug("Second access to {}", uri);
106 resource= resources.getResource(uri);
107 assertThat(resource.exists()).isTrue();
108 assertThat(resource.isModified()).isFalse();
109 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
110 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
111
112 LOG.debug("Third access to {}", uri);
113 resource= resources.getResource(uri);
114 assertThat(resource.exists()).isTrue();
115 assertThat(resource.isModified()).isFalse();
116 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
117 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
118
119 LOG.debug("Fourth access to {} after a pause of 10 seconds -- resource should be expired", uri);
120 CLOCK.timetravel(Duration.ofSeconds(10));
121 assertThat(resource.exists()).isTrue();
122 assertThat(resource.isModified()).isFalse();
123 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
124 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
125
126 LOG.debug("Fifth access to {}", uri);
127 resource= resources.getResource(uri);
128 assertThat(resource.exists()).isTrue();
129 assertThat(resource.isModified()).isFalse();
130 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
131 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
132
133 LOG.debug("Sixth access to {}", uri);
134 resource= resources.getResource(uri);
135 assertThat(resource.exists()).isTrue();
136 assertThat(resource.isModified()).isFalse();
137 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
138 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
139
140 server.verify(FETCH("/remote.html"), exactly(2));
141 server.verify(
142 request()
143 .withPath("/remote.html")
144 .withHeader("If-Modified-Since")
145 .withHeader("If-None-Match"),
146 exactly(1));
147 }
148
149 @Test
150 public void testFetchEncoded() throws Exception
151 {
152 LOG.info("<-- Start of test-case");
153
154
155 String uri = NGINX_URI() + "/remote.html";
156
157 HttpResource resource = resources.getResource(uri);
158
159 assertThat(resource.exists()).isTrue();
160 assertThat(resource.contentType()).isEqualTo(MimeType.valueOf("text/html"));
161 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
162 }
163
164 @Test
165 public void testModifiedResource() throws Exception
166 {
167 LOG.info("<-- Start of test-case");
168
169 String uri = address("/remote.html");
170
171 HttpResource resource;
172
173 resource= resources.getResource(uri);
174
175 LOG.debug("Initial access to resource {}", uri);
176 assertThat(resource.isModified()).isFalse();
177 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
178
179 CLOCK.timetravel(Duration.ofSeconds(10));
180 server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
181
182 LOG.debug("Access to modified resource {} after expiration", uri);
183 assertThat(resource.isModified()).isTrue();
184 assertThat(resource.getInputStream()).hasSameContentAs(modified.getInputStream());
185 assertThat(resource.isModified()).isFalse();
186
187 server.verify(FETCH("/remote.html"), exactly(2));
188 server.verify(
189 request()
190 .withPath("/remote.html")
191 .withHeader("If-Modified-Since")
192 .withHeader("If-None-Match"),
193 exactly(1));
194 }
195
196 @Test
197 public void testModifiedResourceAccessOnly() throws Exception
198 {
199 LOG.info("<-- Start of test-case");
200
201 String uri = address("/remote.html");
202
203 HttpResource resource;
204
205 resource= resources.getResource(uri);
206
207 LOG.debug("Initial access to resource {}", uri);
208 assertThat(resource.getInputStream()).hasSameContentAs(remote.getInputStream());
209
210 CLOCK.timetravel(Duration.ofSeconds(10));
211 server.when(FETCH("/remote.html")).forward(NGINX("/modified.html"));
212
213 LOG.debug("Access to modified resource {} after expiration", uri);
214 assertThat(resource.getInputStream()).hasSameContentAs(modified.getInputStream());
215
216 server.verify(FETCH("/remote.html"), exactly(2));
217 server.verify(
218 request()
219 .withPath("/remote.html")
220 .withHeader("If-Modified-Since")
221 .withHeader("If-None-Match"),
222 exactly(1));
223 }
224
225
226 @SpringBootApplication
227 static class Application
228 {
229 }
230 }