Skip to content

Commit

Permalink
fix: split RPC API and HTTP Gateway servers (#139)
Browse files Browse the repository at this point in the history
To better conform to Kubo's pattern, run the RPC endpoints on port
5001 and the HTTP Gateway on port 8080.

Also simplifies the Docker file, there's no need to rebuild OpenSSL,
the version that comes with `node:20-slim` is fine.
  • Loading branch information
achingbrain authored Apr 11, 2024
1 parent c60ccd8 commit 36625a5
Show file tree
Hide file tree
Showing 18 changed files with 627 additions and 616 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ debugging/test-gateways.log
permutation-logs
*.csv
*.log
blockstore
datastore
*.heapsnapshot

# grafana/prometheus files
config/grafana/alerting
Expand Down
46 changes: 4 additions & 42 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,45 +1,9 @@
# OpenSSL Build Stage
FROM --platform=$BUILDPLATFORM node:20-slim as openssl-builder

RUN apt-get update && \
apt-get install -y build-essential wget && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

ENV OPEN_SSL_VERSION=1.1.1w

# Download OpenSSL
RUN wget -P /tmp https://www.openssl.org/source/old/1.1.1/openssl-${OPEN_SSL_VERSION}.tar.gz

# Extract OpenSSL and configure
RUN mkdir -p /opt/openssl && \
tar -xzf /tmp/openssl-${OPEN_SSL_VERSION}.tar.gz -C /opt/openssl

# Build and install OpenSSL
WORKDIR /opt/openssl/openssl-${OPEN_SSL_VERSION}

# Configure OpenSSL
RUN ./config --prefix=/opt/openssl --openssldir=/opt/openssl/ssl

# Build OpenSSL
RUN make

# Test the build
RUN make test

# Install OpenSSL
RUN make install

# Cleanup unnecessary files to reduce image size
RUN cd /opt/openssl && \
rm -rf /opt/openssl/openssl-${OPEN_SSL_VERSION} /tmp/openssl-${OPEN_SSL_VERSION}.tar.gz

# Application Build Stage
FROM --platform=$BUILDPLATFORM node:20-slim as builder

# Install dependencies required for building the app
RUN apt-get update && \
apt-get install -y tini && \
apt-get install -y build-essential wget tini && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

Expand All @@ -64,12 +28,10 @@ COPY --from=builder /app ./
# copy tini from the builder stage
COPY --from=builder /usr/bin/tini /usr/bin/tini

# copy OpenSSL libraries from the openssl-builder stage
COPY --from=openssl-builder /usr/lib/**/libcrypto* /usr/lib/
COPY --from=openssl-builder /usr/lib/**/libssl* /usr/lib/
COPY --from=openssl-builder /opt/openssl/lib /opt/openssl/lib
ENV LD_LIBRARY_PATH /opt/openssl/lib
# port for RPC API
EXPOSE 5001

# port for HTTP Gateway
EXPOSE 8080

HEALTHCHECK --interval=12s --timeout=12s --start-period=10s CMD node dist/src/healthcheck.js
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,25 +114,25 @@ Note that any of the following calls to docker can be replaced with something li
#### Disable libp2p

```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_LIBP2P="false" helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_LIBP2P="false" helia
```

#### Disable bitswap

```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_BITSWAP="false" helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_BITSWAP="false" helia
```

#### Disable trustless gateways

```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_TRUSTLESS_GATEWAYS="false" helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_TRUSTLESS_GATEWAYS="false" helia
```

#### Customize trustless gateways

```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e TRUSTLESS_GATEWAYS="https://ipfs.io,https://dweb.link" helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e TRUSTLESS_GATEWAYS="https://ipfs.io,https://dweb.link" helia
```

<!--
Expand All @@ -141,9 +141,9 @@ $ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e TRUSTLESS_GATEW
**NOTE:** Not currently supported due to docker volume? issues.
```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" helia
# and if you want to re-use a volume from your host:
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" -v ./datastore:/datastore -v ./blockstore:/blockstore helia
$ docker run -it -p $RPC_PORT:5001 -p $HTTP_PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" -v ./datastore:/datastore -v ./blockstore:/blockstore helia
```
-->

Expand Down
4 changes: 2 additions & 2 deletions debugging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ USE_SUBDOMAINS=true USE_REDIRECTS=false docker build . --platform linux/$(arch)
Then we need to start the container

```sh
docker run -it -p 8080:8080 -e DEBUG="helia-http-gateway*" helia-http-gateway:local-$(arch)
docker run -it -p 5001:5001 -p 8080:8080 -e DEBUG="helia-http-gateway*" helia-http-gateway:local-$(arch)
# or
docker run -it -p 8080:8080 -e DEBUG="helia-http-gateway*" -e USE_REDIRECTS="false" -e USE_SUBDOMAINS="true" helia-http-gateway:local-$(arch)
docker run -it -p 5001:5001 -p 8080:8080 -e DEBUG="helia-http-gateway*" -e USE_REDIRECTS="false" -e USE_SUBDOMAINS="true" helia-http-gateway:local-$(arch)
```

## Running tests against the container
Expand Down
67 changes: 34 additions & 33 deletions debugging/test-gateways.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ trap cleanup_gateway_test EXIT
# Query all endpoints until failure
# This script is intended to be run from the root of the helia-http-gateway repository

PORT=${PORT:-8080}
# If localhost:$PORT is not listening, then exit with non-zero error code
if ! nc -z localhost $PORT; then
echo "localhost:$PORT is not listening"
HTTP_PORT=${HTTP_PORT:-8080}
RPC_PORT=${RPC_PORT:-5001}
# If localhost:$HTTP_PORT is not listening, then exit with non-zero error code
if ! nc -z localhost $HTTP_PORT; then
echo "localhost:$HTTP_PORT is not listening"
exit 1
fi

ensure_gateway_running() {
npx wait-on "tcp:$PORT" -t 1000 || {
npx wait-on "tcp:$HTTP_PORT" -t 1000 || {
EXIT_CODE=1
cleanup_gateway_test
}
Expand All @@ -40,58 +41,58 @@ test_website() {
echo "Requesting $website"
curl -m $max_timeout -s --no-progress-meter -o /dev/null -w "%{url}: HTTP_%{http_code} in %{time_total} seconds (TTFB: %{time_starttransfer}, redirect: %{time_redirect})\n" -L $website
echo "running GC"
curl -X POST -m $max_timeout -s --no-progress-meter -o /dev/null -w "%{url}: HTTP_%{http_code} in %{time_total} seconds\n" http://localhost:$PORT/api/v0/repo/gc
curl -X POST -m $max_timeout -s --no-progress-meter -o /dev/null -w "%{url}: HTTP_%{http_code} in %{time_total} seconds\n" http://localhost:$RPC_PORT/api/v0/repo/gc
}

test_website http://localhost:$PORT/ipns/blog.ipfs.tech
test_website http://localhost:$HTTP_PORT/ipns/blog.ipfs.tech

test_website http://localhost:$PORT/ipns/blog.libp2p.io
test_website http://localhost:$HTTP_PORT/ipns/blog.libp2p.io

test_website http://localhost:$PORT/ipns/consensuslab.world
test_website http://localhost:$HTTP_PORT/ipns/consensuslab.world

test_website http://localhost:$PORT/ipns/docs.ipfs.tech
test_website http://localhost:$HTTP_PORT/ipns/docs.ipfs.tech

test_website http://localhost:$PORT/ipns/docs.libp2p.io
test_website http://localhost:$HTTP_PORT/ipns/docs.libp2p.io

# test_website http://localhost:$PORT/ipns/drand.love #drand.love is not publishing dnslink records
# test_website http://localhost:$HTTP_PORT/ipns/drand.love #drand.love is not publishing dnslink records

test_website http://localhost:$PORT/ipns/fil.org
test_website http://localhost:$HTTP_PORT/ipns/fil.org

test_website http://localhost:$PORT/ipns/filecoin.io
test_website http://localhost:$HTTP_PORT/ipns/filecoin.io

test_website http://localhost:$PORT/ipns/green.filecoin.io
test_website http://localhost:$HTTP_PORT/ipns/green.filecoin.io

test_website http://localhost:$PORT/ipns/ipfs.tech
test_website http://localhost:$HTTP_PORT/ipns/ipfs.tech

test_website http://localhost:$PORT/ipns/ipld.io
test_website http://localhost:$HTTP_PORT/ipns/ipld.io

test_website http://localhost:$PORT/ipns/libp2p.io
test_website http://localhost:$HTTP_PORT/ipns/libp2p.io

test_website http://localhost:$PORT/ipns/n0.computer
test_website http://localhost:$HTTP_PORT/ipns/n0.computer

test_website http://localhost:$PORT/ipns/probelab.io
test_website http://localhost:$HTTP_PORT/ipns/probelab.io

test_website http://localhost:$PORT/ipns/protocol.ai
test_website http://localhost:$HTTP_PORT/ipns/protocol.ai

test_website http://localhost:$PORT/ipns/research.protocol.ai
test_website http://localhost:$HTTP_PORT/ipns/research.protocol.ai

test_website http://localhost:$PORT/ipns/singularity.storage
test_website http://localhost:$HTTP_PORT/ipns/singularity.storage

test_website http://localhost:$PORT/ipns/specs.ipfs.tech
test_website http://localhost:$HTTP_PORT/ipns/specs.ipfs.tech

# test_website http://localhost:$PORT/ipns/strn.network
test_website http://localhost:$PORT/ipns/saturn.tech
# test_website http://localhost:$HTTP_PORT/ipns/strn.network
test_website http://localhost:$HTTP_PORT/ipns/saturn.tech

test_website http://localhost:$PORT/ipns/web3.storage
test_website http://localhost:$HTTP_PORT/ipns/web3.storage

test_website http://localhost:$PORT/ipfs/bafkreiezuss4xkt5gu256vjccx7vocoksxk77vwmdrpwoumfbbxcy2zowq # stock images 3 sec skateboarder video
test_website http://localhost:$HTTP_PORT/ipfs/bafkreiezuss4xkt5gu256vjccx7vocoksxk77vwmdrpwoumfbbxcy2zowq # stock images 3 sec skateboarder video

test_website http://localhost:$PORT/ipfs/bafybeidsp6fva53dexzjycntiucts57ftecajcn5omzfgjx57pqfy3kwbq # big buck bunny
test_website http://localhost:$HTTP_PORT/ipfs/bafybeidsp6fva53dexzjycntiucts57ftecajcn5omzfgjx57pqfy3kwbq # big buck bunny

test_website http://localhost:$PORT/ipfs/bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze # wikipedia
test_website http://localhost:$HTTP_PORT/ipfs/bafybeiaysi4s6lnjev27ln5icwm6tueaw2vdykrtjkwiphwekaywqhcjze # wikipedia

test_website http://localhost:$PORT/ipfs/bafybeifaiclxh6pc3bdtrrkpbvvqqxq6hz5r6htdzxaga4fikfpu2u56qi # uniswap interface
test_website http://localhost:$HTTP_PORT/ipfs/bafybeifaiclxh6pc3bdtrrkpbvvqqxq6hz5r6htdzxaga4fikfpu2u56qi # uniswap interface

test_website http://localhost:$PORT/ipfs/bafybeiae366charqmeewxags5b2jxtkhfmqyyagvqhrr5l7l7xfpp5ikpa # cid.ipfs.tech
test_website http://localhost:$HTTP_PORT/ipfs/bafybeiae366charqmeewxags5b2jxtkhfmqyyagvqhrr5l7l7xfpp5ikpa # cid.ipfs.tech

test_website http://localhost:$PORT/ipfs/bafybeiedlhslivmuj2iinnpd24ulx3fyd7cjenddbkeoxbf3snjiz3npda # docs.ipfs.tech
test_website http://localhost:$HTTP_PORT/ipfs/bafybeiedlhslivmuj2iinnpd24ulx3fyd7cjenddbkeoxbf3snjiz3npda # docs.ipfs.tech
7 changes: 4 additions & 3 deletions debugging/time-permutations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
# export DEBUG="helia*,helia*:trace,libp2p*,libp2p*:trace"
export DEBUG="*,*:trace"
unset FASTIFY_DEBUG
export PORT=8080
export HTTP_PORT=8080
export RPC_PORT=5001
export HOST="0.0.0.0"
export ECHO_HEADERS=false
export METRICS=true
Expand Down Expand Up @@ -47,7 +48,7 @@ echo "USE_SUBDOMAINS,USE_BITSWAP,USE_TRUSTLESS_GATEWAYS,USE_LIBP2P,USE_DELEGATED

run_test() {

npx wait-on "tcp:$PORT" -t 10000 -r # wait for the port to be released
npx wait-on "tcp:$HTTP_PORT" -t 10000 -r # wait for the port to be released

config_id="USE_SUBDOMAINS=$USE_SUBDOMAINS,USE_BITSWAP=$USE_BITSWAP,USE_TRUSTLESS_GATEWAYS=$USE_TRUSTLESS_GATEWAYS,USE_LIBP2P=$USE_LIBP2P,USE_DELEGATED_ROUTING=$USE_DELEGATED_ROUTING"
# if we cannot get any data, we should skip this run.. we need at least USE_BITSWAP enabled, plus either USE_LIBP2P or USE_DELEGATED_ROUTING
Expand Down Expand Up @@ -133,7 +134,7 @@ cleanup_permutations() {
echo "sent TERM signal to subshell"
wait $subshell_pid # wait for the process to exit

npx wait-on "tcp:$PORT" -t 10000 -r # wait for the port to be released
npx wait-on "tcp:$HTTP_PORT" -t 10000 -r # wait for the port to be released

exit 1
}
Expand Down
17 changes: 9 additions & 8 deletions debugging/until-death.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ fi

# You have to pass `DEBUG=" " to disable debugging when using this script`
export DEBUG=${DEBUG:-"helia-http-gateway,helia-http-gateway:server,helia-http-gateway:*:helia-fetch"}
export PORT=${PORT:-8080}
export HTTP_PORT=${HTTP_PORT:-8080}
export RPC_PORT=${RPC_PORT:-5001}
EXIT_CODE=0

cleanup_until_death_called=false
Expand All @@ -20,13 +21,12 @@ cleanup_until_death() {
echo "cleanup_until_death called"
cleanup_until_death_called=true
if [ "$gateway_already_running" != true ]; then
lsof -i TCP:$PORT | grep LISTEN | awk '{print $2}' | xargs --no-run-if-empty kill -9
lsof -i TCP:$HTTP_PORT | grep LISTEN | awk '{print $2}' | xargs --no-run-if-empty kill -9

echo "waiting for the gateway to exit"
npx wait-on "tcp:$PORT" -t 10000 -r # wait for the port to be released
npx wait-on "tcp:$HTTP_PORT" -t 10000 -r # wait for the port to be released
fi


exit $EXIT_CODE
}

Expand All @@ -35,7 +35,8 @@ trap cleanup_until_death EXIT
# Before starting, output all env vars that helia-http-gateway uses
echo "DEBUG=$DEBUG"
echo "FASTIFY_DEBUG=$FASTIFY_DEBUG"
echo "PORT=$PORT"
echo "HTTP_PORT=$HTTP_PORT"
echo "RPC_PORT=$RPC_PORT"
echo "HOST=$HOST"
echo "USE_SUBDOMAINS=$USE_SUBDOMAINS"
echo "METRICS=$METRICS"
Expand All @@ -51,7 +52,7 @@ echo "FILE_BLOCKSTORE_PATH=$FILE_BLOCKSTORE_PATH"
echo "ALLOW_UNHANDLED_ERROR_RECOVERY=$ALLOW_UNHANDLED_ERROR_RECOVERY"

gateway_already_running=false
if nc -z localhost $PORT; then
if nc -z localhost $HTTP_PORT; then
echo "gateway is already running"
gateway_already_running=true
fi
Expand All @@ -70,15 +71,15 @@ start_gateway() {
(node --trace-warnings dist/src/index.js) &
process_id=$!
# echo "process id: $!"
npx wait-on "tcp:$PORT" -t 10000 || {
npx wait-on "tcp:$HTTP_PORT" -t 10000 || {
EXIT_CODE=1
cleanup_until_death
}
}
start_gateway

ensure_gateway_running() {
npx wait-on "tcp:$PORT" -t 5000 || {
npx wait-on "tcp:$HTTP_PORT" -t 5000 || {
EXIT_CODE=1
cleanup_until_death
}
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/gc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { test, expect } from '@playwright/test'
import { PORT } from '../src/constants.js'
import { RPC_PORT } from '../src/constants.js'

test('POST /api/v0/repo/gc', async ({ page }) => {
const result = await page.request.post(`http://localhost:${PORT}/api/v0/repo/gc`)
const result = await page.request.post(`http://localhost:${RPC_PORT}/api/v0/repo/gc`)
expect(result?.status()).toBe(200)

const maybeContent = await result?.text()
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/smoketest.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test'
import { PORT } from '../src/constants.js'
import { HTTP_PORT } from '../src/constants.js'

// test all the same pages listed at https://probelab.io/websites/
const pages = [
Expand Down Expand Up @@ -36,7 +36,7 @@ test.beforeEach(async ({ context }) => {
})

pages.forEach((pagePath) => {
const url = `http://${pagePath}.ipns.localhost:${PORT}`
const url = `http://${pagePath}.ipns.localhost:${HTTP_PORT}`
test(`helia-http-gateway can load path '${url}'`, async ({ page }) => {
// only wait for 'commit' because we don't want to wait for all the assets to load, we just want to make sure that they *would* load (e.g. the html is valid)
const heliaGatewayResponse = await page.goto(`${url}`, { waitUntil: 'commit' })
Expand Down
6 changes: 3 additions & 3 deletions e2e-tests/version-response.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test, expect } from '@playwright/test'
import { PORT } from '../src/constants.js'
import { RPC_PORT } from '../src/constants.js'

function validateResponse (content: string): void {
expect(() => JSON.parse(content)).not.toThrow()
Expand All @@ -10,7 +10,7 @@ function validateResponse (content: string): void {
}

test('GET /api/v0/version', async ({ page }) => {
const result = await page.goto(`http://localhost:${PORT}/api/v0/version`)
const result = await page.goto(`http://localhost:${RPC_PORT}/api/v0/version`)
expect(result?.status()).toBe(200)

const maybeContent = await result?.text()
Expand All @@ -19,7 +19,7 @@ test('GET /api/v0/version', async ({ page }) => {
})

test('POST /api/v0/version', async ({ page }) => {
const result = await page.request.post(`http://localhost:${PORT}/api/v0/version`)
const result = await page.request.post(`http://localhost:${RPC_PORT}/api/v0/version`)
expect(result?.status()).toBe(200)

const maybeContent = await result?.text()
Expand Down
Loading

0 comments on commit 36625a5

Please sign in to comment.