@@ -991,37 +991,40 @@ export function readKey(r: NginxHTTPRequest): string {
991
991
* Given a request and suffix that indicates whether the caller wants the cert
992
992
* or key, return the requested object from cache if possible, falling back to
993
993
* disk.
994
- * @param {NginxHTTPRequest } r - The Nginx HTTP request object.
995
- * @param {string } suffix - The file suffix that indicates whether we want a cert or key
996
- * @returns {string } - The contents of the cert or key
994
+ * @param {NginxHTTPRequest } r The Nginx HTTP request object.
995
+ * @param {string } suffix The file suffix that indicates whether we want a cert or key
996
+ * @returns {string } The contents of the cert or key
997
997
*/
998
998
function readCertOrKey (
999
999
r : NginxHTTPRequest ,
1000
1000
suffix : typeof CERTIFICATE_SUFFIX | typeof KEY_SUFFIX
1001
1001
) : string {
1002
1002
let data = ''
1003
- const prefix = acmeDir ( r )
1004
- const commonName = acmeCommonName ( r )
1005
- const zone = acmeZoneName ( r )
1006
- const path = joinPaths ( prefix , commonName + suffix )
1007
- const key = [ 'acme' , path ] . join ( ':' )
1003
+ const base = certOrKeyBase ( r )
1004
+ const path = base + suffix
1005
+ const key = cacheKey ( path )
1008
1006
1009
- // if the zone is not defined in nginx.conf, then we will bypass the cache
1010
- const cache = zone && ngx . shared && ngx . shared [ zone ]
1007
+ const cache = ngxSharedDict ( r )
1011
1008
1009
+ // ensure the shared dict zone is configured before checking cache
1012
1010
if ( cache ) {
1013
1011
data = ( cache . get ( key ) as string ) || ''
1014
1012
if ( data ) {
1013
+ // Return cached value
1015
1014
return data
1016
1015
}
1017
1016
}
1017
+
1018
+ // filesystem fallback
1018
1019
try {
1019
1020
data = fs . readFileSync ( path , 'utf8' )
1020
1021
} catch ( e ) {
1021
1022
log . error ( 'error reading from file:' , path , `. Error=${ e } ` )
1022
1023
return ''
1023
1024
}
1025
+ // try caching value read from disk in the shared dict zone, if configured
1024
1026
if ( cache && data ) {
1027
+ const zone = acmeZoneName ( r )
1025
1028
try {
1026
1029
cache . set ( key , data )
1027
1030
log . debug ( `wrote to cache: ${ key } zone: ${ zone } ` )
@@ -1032,3 +1035,58 @@ function readCertOrKey(
1032
1035
}
1033
1036
return data
1034
1037
}
1038
+
1039
+ /**
1040
+ * Returns the NGINX shared dict zone if configured.
1041
+ * @param r - The request or periodic session
1042
+ * @returns Shared dict zone or `null`
1043
+ */
1044
+ function ngxSharedDict (
1045
+ r : NginxHTTPRequest | NginxPeriodicSession
1046
+ ) : NgxSharedDict | null {
1047
+ const zone = acmeZoneName ( r )
1048
+ if ( zone && ngx . shared ) {
1049
+ const sharedZone = ngx . shared [ zone ]
1050
+ if ( sharedZone ) {
1051
+ return sharedZone
1052
+ }
1053
+ }
1054
+ return null
1055
+ }
1056
+
1057
+ /**
1058
+ * Removes cached cert and key from the shared dict zone, if applicable.
1059
+ * @param r - The request or periodic session
1060
+ */
1061
+ export function purgeCachedCertKey (
1062
+ r : NginxHTTPRequest | NginxPeriodicSession
1063
+ ) : void {
1064
+ const objPrefix = certOrKeyBase ( r )
1065
+ const cache = ngxSharedDict ( r )
1066
+
1067
+ if ( cache ) {
1068
+ cache . delete ( cacheKey ( objPrefix + CERTIFICATE_SUFFIX ) )
1069
+ cache . delete ( cacheKey ( objPrefix + KEY_SUFFIX ) )
1070
+ }
1071
+ }
1072
+
1073
+ /**
1074
+ * Prepend our namespace to a given cache key
1075
+ * @param key Path to the cert or key
1076
+ * @returns Shared dict cache ke
1077
+ */
1078
+ function cacheKey ( key : string ) {
1079
+ return 'acme:' + key
1080
+ }
1081
+
1082
+ /**
1083
+ * Returns the base path to store a cert or key
1084
+ * @param path Path to the cert or key
1085
+ * @returns Path string
1086
+ */
1087
+ function certOrKeyBase ( r : NginxHTTPRequest | NginxPeriodicSession ) : string {
1088
+ const prefix = acmeDir ( r )
1089
+ const commonName = acmeCommonName ( r )
1090
+ const path = joinPaths ( prefix , commonName )
1091
+ return path
1092
+ }
0 commit comments