PluginProbe
Surge / 1.2.0
Surge v1.2.0
trunk 0.1.0 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.2.0 1.2.1
surge / include / cache.php

cache.php in Surge 1.2.0, at include/cache.php

134 lines 2.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Cache Content
4 *
5 * This file is loaded when there's a chance the request content should be
6 * saved to cache.
7 *
8 * @package Surge
9 */
10
11 namespace Surge;
12
13 if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
14 return;
15 }
16
17 include_once( __DIR__ . '/common.php' );
18
19 /**
20 * The main output buffer callback.
21 *
22 * @param string $contents The buffer contents.
23 *
24 * @return string Contents.
25 */
26 $ob_callback = function( $contents ) {
27 $ttl = config( 'ttl' );
28
29 if ( $ttl < 1 ) {
30 header( 'X-Cache: bypass' );
31 status( 'bypass' );
32 return $contents;
33 }
34
35 $skip = false;
36 $headers = [];
37
38 foreach ( headers_list() as $header ) {
39 list( $name, $value ) = array_map( 'trim', explode( ':', $header, 2 ) );
40
41 // Do not store or vary on these headers.
42 if ( in_array( strtolower( $name ), ['x-cache', 'x-powered-by'] ) ) {
43 continue;
44 }
45
46 $headers[ $name ][] = $value;
47
48 if ( strtolower( $name ) == 'set-cookie' ) {
49 $skip = true;
50 break;
51 }
52
53 if ( strtolower( $name ) == 'cache-control' ) {
54 if ( stripos( $value, 'no-cache' ) !== false || stripos( $value, 'max-age=0' ) !== false ) {
55 $skip = true;
56 break;
57 }
58 }
59 }
60
61 if ( ! empty( $_SERVER['HTTP_AUTHORIZATION'] ) ) {
62 $skip = true;
63 }
64
65 if ( ! in_array( strtoupper( $_SERVER['REQUEST_METHOD'] ), [ 'GET', 'HEAD' ] ) ) {
66 $skip = true;
67 }
68
69 if ( ! in_array( http_response_code(), [ 200, 301, 302, 404 ] ) ) {
70 $skip = true;
71 }
72
73 if ( defined( 'DONOTCACHEPAGE' ) && DONOTCACHEPAGE ) {
74 $skip = true;
75 }
76
77 if ( $skip ) {
78 header( 'X-Cache: bypass' );
79 status( 'bypass' );
80 return $contents;
81 }
82
83 $key = key();
84
85 $meta = [
86 'code' => http_response_code(),
87 'headers' => $headers,
88 'created' => time(),
89 'expires' => time() + $ttl,
90 'flags' => array_unique( flag() ),
91 'path' => $key['path'],
92 ];
93
94 $meta_json = json_encode( $meta );
95 $cache_key = md5( json_encode( $key ) );
96 $level = substr( $cache_key, -2 );
97
98 if ( ! wp_mkdir_p( CACHE_DIR . "/{$level}/" ) ) {
99 return $contents;
100 }
101
102 // Open a new cache file.
103 $hash = wp_generate_password( 6, false );
104 $f = fopen( CACHE_DIR . "/{$level}/{$cache_key}.{$hash}.php", 'xb' );
105
106 // Could not create file.
107 if ( false === $f ) {
108 header( 'X-Cache: bypass' );
109 status( 'bypass' );
110 return $contents;
111 }
112
113 fwrite( $f, '<?php exit; ?>' );
114 fwrite( $f, pack( 'L', strlen( $meta_json ) ) );
115 fwrite( $f, $meta_json );
116 fwrite( $f, $contents );
117
118 // Close the file.
119 fclose( $f );
120
121 // Atomic (hopefully) rename.
122 if ( ! rename( CACHE_DIR . "/{$level}/{$cache_key}.{$hash}.php",
123 CACHE_DIR . "/{$level}/{$cache_key}.php" )
124 ) {
125 unlink( CACHE_DIR . "/{$level}/{$cache_key}.{$hash}.php" );
126 }
127
128 event( 'request', [ 'meta' => $meta, 'status' => status() ] );
129 return $contents;
130 };
131
132 // Attach to main output buffer.
133 ob_start( $ob_callback );
134