18
18
import { default as cors } from 'cors' ;
19
19
import express from 'express' ;
20
20
//import * as OpenApiValidator from 'express-openapi-validator';
21
- import promMid from 'express-prometheus-middleware' ;
22
21
import fs from 'node:fs' ;
23
- import swaggerUi from 'swagger-ui-express' ;
24
22
import YAML from 'yaml' ;
25
23
26
24
import * as config from './config.js' ;
27
25
import log from './log.js' ;
26
+ import { addCapability } from './middleware/ANS-101.js' ;
27
+ import { createGatewayApiDocsMiddleware } from './middleware/api-docs.js' ;
28
+ import {
29
+ createArIoAdminMiddleware ,
30
+ createArIoCoreMiddleware ,
31
+ } from './middleware/ar-io.js' ;
28
32
import { createArnsMiddleware } from './middleware/arns.js' ;
33
+ import { createDataMiddleware } from './middleware/data.js' ;
34
+ import { createGraphQLMiddleware } from './middleware/graphql.js' ;
35
+ import { createMetricsMiddleware } from './middleware/metrics.js' ;
29
36
import { createSandboxMiddleware } from './middleware/sandbox.js' ;
30
- import {
31
- DATA_PATH_REGEX ,
32
- RAW_DATA_PATH_REGEX ,
33
- createDataHandler ,
34
- createRawDataHandler ,
35
- } from './routes/data.js' ;
36
- import { apolloServer } from './routes/graphql/index.js' ;
37
+ import { ArweaveG8wayMiddleware } from './middleware/types.js' ;
37
38
import * as system from './system.js' ;
38
39
39
40
system . arweaveClient . refreshPeers ( ) ;
@@ -55,148 +56,50 @@ const app = express();
55
56
56
57
app . use ( cors ( ) ) ;
57
58
58
- app . use (
59
- promMid ( {
60
- metricsPath : '/ar-io/__gateway_metrics' ,
61
- extraMasks : [
62
- // Mask all paths except for the ones below
63
- / ^ (? ! a p i - d o c s ) (? ! a r - i o ) (? ! g r a p h q l ) (? ! o p e n a p i \. j s o n ) (? ! r a w ) .+ $ / ,
64
- // Mask Arweave TX IDs
65
- / [ a - z A - Z 0 - 9 _ - ] { 43 } / ,
66
- ] ,
67
- } ) ,
68
- ) ;
69
-
70
- const dataHandler = createDataHandler ( {
71
- log,
72
- dataIndex : system . contiguousDataIndex ,
73
- dataSource : system . contiguousDataSource ,
74
- blockListValidator : system . blockListValidator ,
75
- manifestPathResolver : system . manifestPathResolver ,
76
- } ) ;
77
-
78
- app . use (
59
+ const coreG8wayMiddleware = [
60
+ createMetricsMiddleware ( ) ,
79
61
createArnsMiddleware ( {
80
- dataHandler,
62
+ log,
63
+ dataIndex : system . contiguousDataIndex ,
64
+ dataSource : system . contiguousDataSource ,
65
+ blockListValidator : system . blockListValidator ,
66
+ manifestPathResolver : system . manifestPathResolver ,
81
67
nameResolver : system . nameResolver ,
82
68
} ) ,
83
- ) ;
84
-
85
- app . use (
86
69
createSandboxMiddleware ( {
87
70
rootHost : config . ARNS_ROOT_HOST ,
88
71
sandboxProtocol : config . SANDBOX_PROTOCOL ,
89
72
} ) ,
90
- ) ;
91
-
92
- // OpenAPI Spec
93
- const openapiDocument = YAML . parse (
94
- fs . readFileSync ( 'docs/openapi.yaml' , 'utf8' ) ,
95
- ) ;
96
- app . get ( '/openapi.json' , ( _req , res ) => {
97
- res . json ( openapiDocument ) ;
98
- } ) ;
99
-
100
- // Swagger UI
101
- const options = {
102
- explorer : true ,
103
- } ;
104
- app . use (
105
- '/api-docs' ,
106
- swaggerUi . serve ,
107
- swaggerUi . setup ( openapiDocument , options ) ,
108
- ) ;
109
-
110
- // Healthcheck
111
- app . get ( '/ar-io/healthcheck' , ( _req , res ) => {
112
- const data = {
113
- uptime : process . uptime ( ) ,
114
- message : 'Welcome to the Permaweb.' ,
115
- date : new Date ( ) ,
116
- } ;
117
-
118
- res . status ( 200 ) . send ( data ) ;
119
- } ) ;
120
-
121
- // ar.io network info
122
- app . get ( '/ar-io/info' , ( _req , res ) => {
123
- res . status ( 200 ) . send ( {
124
- wallet : config . AR_IO_WALLET ,
125
- } ) ;
126
- } ) ;
127
-
128
- // Only allow access to admin routes if the bearer token matches the admin api key
129
- app . use ( '/ar-io/admin' , ( req , res , next ) => {
130
- if ( req . headers . authorization === `Bearer ${ config . ADMIN_API_KEY } ` ) {
131
- next ( ) ;
132
- } else {
133
- res . status ( 401 ) . send ( 'Unauthorized' ) ;
134
- }
135
- } ) ;
136
-
137
- // Debug info (for internal use)
138
- app . get ( '/ar-io/admin/debug' , async ( _req , res ) => {
139
- res . json ( {
140
- db : await system . db . getDebugInfo ( ) ,
141
- } ) ;
142
- } ) ;
143
-
144
- // Block access to contiguous data by ID or hash
145
- app . put ( '/ar-io/admin/block-data' , express . json ( ) , async ( req , res ) => {
146
- // TODO improve validation
147
- try {
148
- const { id, hash, source, notes } = req . body ;
149
- if ( id === undefined && hash === undefined ) {
150
- res . status ( 400 ) . send ( "Must provide 'id' or 'hash'" ) ;
151
- return ;
152
- }
153
- system . db . blockData ( { id, hash, source, notes } ) ;
154
- // TODO check return value
155
- res . json ( { message : 'Content blocked' } ) ;
156
- } catch ( error : any ) {
157
- res . status ( 500 ) . send ( error ?. message ) ;
158
- }
159
- } ) ;
160
-
161
- // Queue a TX ID for processing
162
- app . post ( '/ar-io/admin/queue-tx' , express . json ( ) , async ( req , res ) => {
163
- try {
164
- const { id } = req . body ;
165
- if ( id === undefined ) {
166
- res . status ( 400 ) . send ( "Must provide 'id'" ) ;
167
- return ;
168
- }
169
- system . prioritizedTxIds . add ( id ) ;
170
- system . txFetcher . queueTxId ( id ) ;
171
- res . json ( { message : 'TX queued' } ) ;
172
- } catch ( error : any ) {
173
- res . status ( 500 ) . send ( error ?. message ) ;
174
- }
175
- } ) ;
176
-
177
- // GraphQL
178
- const apolloServerInstanceGql = apolloServer ( system . db , {
179
- introspection : true ,
180
- } ) ;
181
- apolloServerInstanceGql . start ( ) . then ( ( ) => {
182
- apolloServerInstanceGql . applyMiddleware ( {
183
- app,
184
- path : '/graphql' ,
185
- } ) ;
186
- app . listen ( config . PORT , ( ) => {
187
- log . info ( `Listening on port ${ config . PORT } ` ) ;
188
- } ) ;
189
- } ) ;
190
-
191
- // Data routes
192
- app . get (
193
- RAW_DATA_PATH_REGEX ,
194
- createRawDataHandler ( {
73
+ createGatewayApiDocsMiddleware ( {
74
+ openapiDocument : YAML . parse ( fs . readFileSync ( 'docs/openapi.yaml' , 'utf8' ) ) ,
75
+ } ) ,
76
+ // TODO: use config schema to parse config for correctness instead of trusting types.
77
+ createArIoCoreMiddleware ( { AR_IO_WALLET : config . AR_IO_WALLET as string } ) ,
78
+ createArIoAdminMiddleware ( {
79
+ db : system . db ,
80
+ prioritizedTxIds : system . prioritizedTxIds ,
81
+ txFetcher : system . txFetcher ,
82
+ ADMIN_API_KEY : config . ADMIN_API_KEY ,
83
+ } ) ,
84
+ createGraphQLMiddleware ( system ) ,
85
+ createDataMiddleware ( {
195
86
log,
196
87
dataIndex : system . contiguousDataIndex ,
197
88
dataSource : system . contiguousDataSource ,
198
89
blockListValidator : system . blockListValidator ,
90
+ manifestPathResolver : system . manifestPathResolver ,
199
91
} ) ,
200
- ) ;
201
-
202
- app . get ( DATA_PATH_REGEX , dataHandler ) ;
92
+ ] ;
93
+
94
+ // TODO: implement dynamically importing middleware
95
+ const dynamicallyAddedG8wayMiddleware : Promise < ArweaveG8wayMiddleware > [ ] = [ ] ;
96
+
97
+ [ ...coreG8wayMiddleware ]
98
+ . reduce (
99
+ ( $app , middleware ) =>
100
+ middleware ( { addCapability } ) . then ( async ( m ) => m ( await $app ) ) ,
101
+ Promise . resolve ( app ) ,
102
+ )
103
+ . then ( ( app ) => {
104
+ app . listen ( config . PORT , ( ) => log . info ( `Listening on port ${ config . PORT } ` ) ) ;
105
+ } ) ;
0 commit comments