8
8
import javax .net .ssl .SSLContext ;
9
9
import javax .net .ssl .TrustManager ;
10
10
import javax .net .ssl .X509TrustManager ;
11
+ import java .io .File ;
12
+ import java .io .FileOutputStream ;
11
13
import java .io .IOException ;
12
14
import java .net .InetSocketAddress ;
13
15
import java .net .Proxy ;
16
18
import java .net .http .HttpClient ;
17
19
import java .net .http .HttpRequest ;
18
20
import java .net .http .HttpResponse ;
21
+ import java .nio .file .Files ;
22
+ import java .nio .file .attribute .FileTime ;
19
23
import java .security .cert .X509Certificate ;
24
+ import java .text .SimpleDateFormat ;
20
25
import java .time .Duration ;
21
- import java .util .Arrays ;
22
- import java .util .List ;
26
+ import java .util .*;
23
27
24
28
public class HttpTiny extends PerlModuleBase {
25
29
@@ -32,7 +36,8 @@ public static void initialize() {
32
36
httpTiny .initializeExporter ();
33
37
httpTiny .defineExport ("EXPORT" , "new" , "get" , "post" , "request" );
34
38
try {
35
- httpTiny .registerMethod ("request" , "$$" );
39
+ httpTiny .registerMethod ("request" , null );
40
+ httpTiny .registerMethod ("mirror" , null );
36
41
} catch (NoSuchMethodException e ) {
37
42
System .err .println ("Warning: Missing HttpTiny method: " + e .getMessage ());
38
43
}
@@ -188,4 +193,60 @@ private static boolean shouldNotProxy(String host, String noProxy) {
188
193
.toList ();
189
194
return noProxyList .stream ().anyMatch (host ::endsWith );
190
195
}
196
+
197
+ public static RuntimeList mirror (RuntimeArray args , int ctx ) throws Exception {
198
+ if (args .size () < 3 ) {
199
+ throw new IllegalStateException ("Bad number of arguments for HTTP::Tiny->mirror" );
200
+ }
201
+
202
+ RuntimeScalar self = args .get (0 );
203
+ String url = args .get (1 ).toString ();
204
+ String filePath = args .get (2 ).toString ();
205
+ RuntimeHash options = args .size () > 3 ? args .get (3 ).hashDeref () : new RuntimeHash ();
206
+
207
+ File file = new File (filePath );
208
+ if (file .exists ()) {
209
+ // Set If-Modified-Since header
210
+ long lastModified = file .lastModified ();
211
+ SimpleDateFormat dateFormat = new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss z" , Locale .US );
212
+ dateFormat .setTimeZone (TimeZone .getTimeZone ("GMT" ));
213
+ String ifModifiedSince = dateFormat .format (new Date (lastModified ));
214
+
215
+ RuntimeHash headers = options .exists ("headers" ).getBoolean ()
216
+ ? options .get ("headers" ).hashDeref () : new RuntimeHash ();
217
+ headers .put ("If-Modified-Since" , new RuntimeScalar (ifModifiedSince ));
218
+ options .put ("headers" , headers .createReference ());
219
+ }
220
+
221
+ // Perform the request
222
+ RuntimeArray requestArgs = new RuntimeArray ();
223
+ requestArgs .push (self );
224
+ requestArgs .push (new RuntimeScalar ("GET" ));
225
+ requestArgs .push (new RuntimeScalar (url ));
226
+ requestArgs .push (options .createReference ());
227
+
228
+ RuntimeList response = request (requestArgs , ctx );
229
+ RuntimeHash responseHash = ((RuntimeScalar ) response .elements .get (0 )).hashDeref ();
230
+
231
+ // Check if the request was successful or not modified
232
+ boolean success = responseHash .get ("success" ).getBoolean () || responseHash .get ("status" ).getLong () == 304 ;
233
+ if (success && responseHash .get ("status" ).getLong () != 304 ) {
234
+ // Write response content to file
235
+ try (FileOutputStream fos = new FileOutputStream (file )) {
236
+ fos .write (responseHash .get ("content" ).toString ().getBytes ());
237
+ }
238
+
239
+ // Update file modification time if Last-Modified header is present
240
+ RuntimeHash headers = responseHash .get ("headers" ).hashDeref ();
241
+ if (headers .exists ("last-modified" ).getBoolean ()) {
242
+ String lastModifiedStr = headers .get ("last-modified" ).toString ();
243
+ SimpleDateFormat dateFormat = new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss z" , Locale .US );
244
+ dateFormat .setTimeZone (TimeZone .getTimeZone ("GMT" ));
245
+ Date lastModifiedDate = dateFormat .parse (lastModifiedStr );
246
+ Files .setLastModifiedTime (file .toPath (), FileTime .fromMillis (lastModifiedDate .getTime ()));
247
+ }
248
+ }
249
+
250
+ return response ;
251
+ }
191
252
}
0 commit comments