diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index 4b8aecab80..050af99fde 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -38,6 +38,7 @@ class BitcoinRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'difficulty-adjustment', this.getDifficultyChange) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/recommended', this.getRecommendedFees) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/precise', this.getPreciseRecommendedFees) + .get(config.MEMPOOL.API_URL_PREFIX + 'fee-estimates', this.getPreciseRecommendedFeesEsploraTransformed) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/mempool-blocks', this.getMempoolBlocks) .get(config.MEMPOOL.API_URL_PREFIX + 'backend-info', this.getBackendInfo) .get(config.MEMPOOL.API_URL_PREFIX + 'init-data', this.getInitData) @@ -134,6 +135,47 @@ class BitcoinRoutes { res.json(result); } + private getPreciseRecommendedFeesEsploraTransformed(req: Request, res: Response) { + if (!mempool.isInSync()) { + res.statusCode = 503; + res.send('Service Unavailable'); + return; + } + const result = feeApi.getPreciseRecommendedFee(); + + res.json({ + 'warning': 'This endpoint is deprecated and will be removed in a future release. Please use /api/v1/fees/precise instead.', + '1': result.fastestFee, + '2': result.fastestFee, + '3': result.halfHourFee, + '4': result.halfHourFee, + '5': result.halfHourFee, + '6': result.hourFee, + '7': result.hourFee, + '8': result.hourFee, + '9': result.hourFee, + '10': result.hourFee, + '11': result.hourFee, + '12': result.hourFee, + '13': result.hourFee, + '14': result.hourFee, + '15': result.hourFee, + '16': result.hourFee, + '17': result.hourFee, + '18': result.hourFee, + '19': result.hourFee, + '20': result.hourFee, + '21': result.hourFee, + '22': result.hourFee, + '23': result.hourFee, + '24': result.hourFee, + '25': result.hourFee, + '144': result.economyFee, + '504': result.economyFee, + '1008': result.minimumFee, + }); + } + private getMempoolBlocks(req: Request, res: Response) { try { const result = mempoolBlocks.getMempoolBlocks(); diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index 6bbb2d5f32..c17f241d3d 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -13,7 +13,7 @@ RUN npm install --omit=dev --omit=optional RUN npm run build -FROM nginx:1.27.0-alpine +FROM nginx:1.30.1-alpine WORKDIR /patch @@ -21,6 +21,7 @@ COPY --from=builder /build/entrypoint.sh . COPY --from=builder /build/wait-for . COPY --from=builder /build/dist/mempool /var/www/mempool COPY --from=builder /build/nginx.conf /etc/nginx/ +COPY --from=builder /build/http-basic.conf /etc/nginx/ COPY --from=builder /build/nginx-mempool.conf /etc/nginx/conf.d/ RUN chmod +x /patch/entrypoint.sh @@ -30,6 +31,7 @@ RUN chown -R 1000:1000 /patch && chmod -R 755 /patch && \ chown -R 1000:1000 /var/cache/nginx && \ chown -R 1000:1000 /var/log/nginx && \ chown -R 1000:1000 /etc/nginx/nginx.conf && \ + chown -R 1000:1000 /etc/nginx/http-basic.conf && \ chown -R 1000:1000 /etc/nginx/conf.d && \ chown -R 1000:1000 /var/www/mempool diff --git a/docker/init.sh b/docker/init.sh index 3c5ec6aa31..f1cfd222fb 100755 --- a/docker/init.sh +++ b/docker/init.sh @@ -12,6 +12,7 @@ wget -O ./backend/GeoIP/GeoLite2-ASN.mmdb https://raw.githubusercontent.com/memp localhostIP="127.0.0.1" cp ./docker/frontend/* ./frontend cp ./nginx.conf ./frontend/ +cp ./http-basic.conf ./frontend/ cp ./nginx-mempool.conf ./frontend/ sed -i"" -e "s/${localhostIP}:80/0.0.0.0:__MEMPOOL_FRONTEND_HTTP_PORT__/g" ./frontend/nginx.conf sed -i"" -e "s/${localhostIP}/0.0.0.0/g" ./frontend/nginx.conf diff --git a/http-basic.conf b/http-basic.conf new file mode 100644 index 0000000000..90d99c65a5 --- /dev/null +++ b/http-basic.conf @@ -0,0 +1,36 @@ +variables_hash_max_size 4096; +sendfile on; +tcp_nopush on; +tcp_nodelay on; + +server_tokens off; +server_name_in_redirect off; + +access_log /var/log/nginx/access.log; +error_log /var/log/nginx/error.log; + +# reset timed out connections freeing ram +reset_timedout_connection on; +# maximum time between packets the client can pause when sending nginx any data +client_body_timeout 10s; +# maximum time the client has to send the entire header to nginx +client_header_timeout 10s; +# timeout which a single keep-alive client connection will stay open +keepalive_timeout 69s; +# maximum time between packets nginx is allowed to pause when sending the client data +send_timeout 69s; + +# number of requests per connection, does not affect SPDY +keepalive_requests 1337; + +# enable gzip compression +gzip on; +gzip_vary on; +gzip_comp_level 6; +gzip_min_length 1000; +gzip_proxied expired no-cache no-store private auth; +# text/html is always compressed by gzip module +gzip_types application/javascript application/json application/ld+json application/manifest+json application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard; + +# limit request body size +client_max_body_size 10m; diff --git a/nginx.conf b/nginx.conf index 670764e203..c6b261cb0a 100644 --- a/nginx.conf +++ b/nginx.conf @@ -10,45 +10,12 @@ events { } http { - sendfile on; - tcp_nopush on; - tcp_nodelay on; - - server_tokens off; - server_name_in_redirect off; + # HTTP basic configuration + include /etc/nginx/http-basic.conf; include /etc/nginx/mime.types; default_type application/octet-stream; - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - # reset timed out connections freeing ram - reset_timedout_connection on; - # maximum time between packets the client can pause when sending nginx any data - client_body_timeout 10s; - # maximum time the client has to send the entire header to nginx - client_header_timeout 10s; - # timeout which a single keep-alive client connection will stay open - keepalive_timeout 69s; - # maximum time between packets nginx is allowed to pause when sending the client data - send_timeout 69s; - - # number of requests per connection, does not affect SPDY - keepalive_requests 1337; - - # enable gzip compression - gzip on; - gzip_vary on; - gzip_comp_level 6; - gzip_min_length 1000; - gzip_proxied expired no-cache no-store private auth; - # text/html is always compressed by gzip module - gzip_types application/javascript application/json application/ld+json application/manifest+json application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard; - - # limit request body size - client_max_body_size 10m; - # proxy cache proxy_cache off; proxy_cache_path /var/cache/nginx keys_zone=cache:20m levels=1:2 inactive=600s max_size=500m; diff --git a/production/nginx-cache-heater b/production/nginx-cache-heater index e6dea270a3..f0d1db1ca7 100755 --- a/production/nginx-cache-heater +++ b/production/nginx-cache-heater @@ -8,6 +8,7 @@ heat() } heatURLs=( + '/api/fee-estimates' '/api/v1/fees/recommended' '/api/v1/accelerations' ) diff --git a/production/nginx/http-basic.conf b/production/nginx/http-basic.conf index fd5cc4b94a..8988ce74cc 100644 --- a/production/nginx/http-basic.conf +++ b/production/nginx/http-basic.conf @@ -1,4 +1,5 @@ # basics +variables_hash_max_size 4096; sendfile on; tcp_nopush on; tcp_nodelay on; diff --git a/production/nginx/location-api.conf b/production/nginx/location-api.conf index c7fabfb696..686b80dca9 100644 --- a/production/nginx/location-api.conf +++ b/production/nginx/location-api.conf @@ -50,6 +50,12 @@ location /api/v1 { # esplora # ########### +# route /api/fee-estimates to mempool backend instead of esplora +location = /api/fee-estimates { + rewrite ^/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-api-v1-cache-hot; +} + # it's ok to cache blockchain data "forever", so we do 30d location /api/block/ { rewrite ^/api/(.*) /$1 break; diff --git a/production/nginx/location-signet-api.conf b/production/nginx/location-signet-api.conf index d3292b424a..c184c42729 100644 --- a/production/nginx/location-signet-api.conf +++ b/production/nginx/location-signet-api.conf @@ -42,6 +42,12 @@ location /signet/api/v1 { # esplora # ########### +# route /signet/api/fee-estimates to mempool backend instead of esplora +location = /signet/api/fee-estimates { + rewrite ^/signet/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-signet-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /signet/api/block/ { rewrite ^/signet/api/(.*) /$1 break; diff --git a/production/nginx/location-testnet-api.conf b/production/nginx/location-testnet-api.conf index d43a51ce51..4b9433bb81 100644 --- a/production/nginx/location-testnet-api.conf +++ b/production/nginx/location-testnet-api.conf @@ -42,6 +42,12 @@ location /testnet/api/v1 { # esplora # ########### +# route /testnet/api/fee-estimates to mempool backend instead of esplora +location = /testnet/api/fee-estimates { + rewrite ^/testnet/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-testnet-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /testnet/api/block/ { rewrite ^/testnet/api/(.*) /$1 break; diff --git a/production/nginx/location-testnet4-api.conf b/production/nginx/location-testnet4-api.conf index 1df5023179..11600d9e2c 100644 --- a/production/nginx/location-testnet4-api.conf +++ b/production/nginx/location-testnet4-api.conf @@ -42,6 +42,12 @@ location /testnet4/api/v1 { # esplora # ########### +# route /testnet4/api/fee-estimates to mempool backend instead of esplora +location = /testnet4/api/fee-estimates { + rewrite ^/testnet4/api/(.*) /api/v1/$1 break; + try_files /dev/null @mempool-testnet4-api-v1-cache-normal; +} + # it's ok to cache blockchain data "forever", so we do 30d location /testnet4/api/block/ { rewrite ^/testnet4/api/(.*) /$1 break;