@@ -37,11 +37,34 @@ export const createArnsMiddleware = ({
37
37
nameResolver : NameResolver ;
38
38
} ) : Handler =>
39
39
asyncMiddleware ( async ( req , res , next ) => {
40
+ // Skip all ArNS processing if the root ArNS host is not set.
41
+ if ( config . ARNS_ROOT_HOST !== undefined && config . ARNS_ROOT_HOST !== '' ) {
42
+ next ( ) ;
43
+ return ;
44
+ }
45
+
46
+ const hostNameIsArNSRoot = req . hostname === config . ARNS_ROOT_HOST ;
47
+
48
+ if (
49
+ // Use apex ID as ArNS root data if it's set.
50
+ config . APEX_TX_ID !== undefined &&
51
+ hostNameIsArNSRoot
52
+ ) {
53
+ res . header ( headerNames . arnsResolvedId , config . APEX_TX_ID ) ;
54
+ dataHandler ( req , res , next ) ;
55
+ }
56
+
57
+ let arnsSubdomain : string | undefined ;
40
58
if (
41
- // Ignore requests that do end with the ArNS root hostname.
42
- ( config . ARNS_ROOT_HOST !== undefined &&
43
- config . ARNS_ROOT_HOST !== '' &&
44
- ! req . hostname . endsWith ( '.' + config . ARNS_ROOT_HOST ) ) ||
59
+ // If apex ArNS name is set and hostname matches root use the apex ArNS
60
+ // name as the ArNS subdomain.
61
+ config . APEX_ARNS_NAME !== undefined &&
62
+ hostNameIsArNSRoot
63
+ ) {
64
+ arnsSubdomain = config . APEX_ARNS_NAME ;
65
+ } else if (
66
+ // Ignore requests that do not end with the ArNS root hostname.
67
+ ! req . hostname . endsWith ( '.' + config . ARNS_ROOT_HOST ) ||
45
68
// Ignore requests that do not include subdomains since ArNS always
46
69
// requires a subdomain.
47
70
! Array . isArray ( req . subdomains ) ||
@@ -51,22 +74,22 @@ export const createArnsMiddleware = ({
51
74
) {
52
75
next ( ) ;
53
76
return ;
77
+ } else {
78
+ arnsSubdomain = req . subdomains [ req . subdomains . length - 1 ] ;
54
79
}
55
80
56
- const arnsSubdomain = req . subdomains [ req . subdomains . length - 1 ] ;
57
-
58
81
if (
59
82
EXCLUDED_SUBDOMAINS . has ( arnsSubdomain ) ||
60
- // Avoid collisions with sandbox URLs by ensuring the subdomain length
61
- // is below the minimum length of a sandbox subdomain. Undernames are
62
- // are an exception because they can be longer and '_' cannot appear in
63
- // base32.
83
+ // Avoid collisions with sandbox URLs by ensuring the subdomain length is
84
+ // below the minimum length of a sandbox subdomain. Undernames are are an
85
+ // exception because they can be longer and '_' cannot appear in base32.
64
86
( arnsSubdomain . length > MAX_ARNS_NAME_LENGTH && ! arnsSubdomain . match ( / _ / ) )
65
87
) {
66
88
next ( ) ;
67
89
return ;
68
90
}
69
91
92
+ // TODO: add comment explaining this behavior
70
93
if ( DATA_PATH_REGEX . test ( req . path ) ) {
71
94
next ( ) ;
72
95
return ;
@@ -77,34 +100,55 @@ export const createArnsMiddleware = ({
77
100
return ;
78
101
}
79
102
80
- // NOTE: Errors and request deduplication are expected to be handled by the
81
- // resolver
103
+ // NOTE: Errors and in-flight resolution deduplication are expected to be
104
+ // handled by the resolver.
82
105
const end = metrics . arnsResolutionTime . startTimer ( ) ;
83
- const { resolvedId, ttl, processId, resolvedAt, limit, index } =
106
+ let { resolvedId, ttl, processId, resolvedAt, limit, index } =
84
107
await nameResolver . resolve ( {
85
108
name : arnsSubdomain ,
86
109
} ) ;
87
110
end ( ) ;
88
111
if ( resolvedId === undefined ) {
89
- sendNotFound ( res ) ;
90
- return ;
112
+ res . status ( 404 ) ;
113
+ if (
114
+ // ArNS undername should not use custom 404 pages.
115
+ // TODO: expand this explanation
116
+ arnsSubdomain . match ( / _ / ) ||
117
+ // Custom 404s should not be used for Apex ArNS.
118
+ hostNameIsArNSRoot
119
+ ) {
120
+ sendNotFound ( res ) ;
121
+ } else if ( config . ARNS_NOT_FOUND_TX_ID !== undefined ) {
122
+ resolvedId = config . ARNS_NOT_FOUND_TX_ID ;
123
+ } else if ( config . ARNS_NOT_FOUND_ARNS_NAME !== undefined ) {
124
+ ( { resolvedId, ttl, processId, resolvedAt, limit, index } =
125
+ await nameResolver . resolve ( {
126
+ name : arnsSubdomain ,
127
+ } ) ) ;
128
+ } else {
129
+ sendNotFound ( res ) ;
130
+ return ;
131
+ }
91
132
}
92
133
93
134
res . header ( headerNames . arnsResolvedId , resolvedId ) ;
94
- res . header ( headerNames . arnsTtlSeconds , ttl . toString ( ) ) ;
135
+ res . header ( headerNames . arnsTtlSeconds , ttl ? .toString ( ) ) ;
95
136
res . header ( headerNames . arnsProcessId , processId ) ;
96
- res . header ( headerNames . arnsResolvedAt , resolvedAt . toString ( ) ) ;
97
- // limit and index can be undefined if they come from the cache
98
- res . header ( headerNames . arnsLimit , limit ?. toString ( ) ) ;
99
- res . header ( headerNames . arnsIndex , index ?. toString ( ) ) ;
137
+ res . header ( headerNames . arnsResolvedAt , resolvedAt ?. toString ( ) ) ;
138
+ // Limit and index can be undefined if they come from a cache that existed
139
+ // before they were added.
140
+ if ( limit !== undefined && index !== undefined ) {
141
+ res . header ( headerNames . arnsLimit , limit . toString ( ) ) ;
142
+ res . header ( headerNames . arnsIndex , index . toString ( ) ) ;
100
143
101
- // handle undername limit exceeded
102
- if ( config . ARNS_RESOLVER_ENFORCE_UNDERNAME_LIMIT && index > limit ) {
103
- sendPaymentRequired (
104
- res ,
105
- 'ArNS undername limit exceeded. Purchase additional undernames to continue.' ,
106
- ) ;
107
- return ;
144
+ // handle undername limit exceeded
145
+ if ( config . ARNS_RESOLVER_ENFORCE_UNDERNAME_LIMIT && index > limit ) {
146
+ sendPaymentRequired (
147
+ res ,
148
+ 'ArNS undername limit exceeded. Purchase additional undernames to continue.' ,
149
+ ) ;
150
+ return ;
151
+ }
108
152
}
109
153
110
154
// TODO: add a header for arns cache status
0 commit comments