#Bind Express App to IPv6?

1 messages · Page 1 of 1 (latest)

stable cedar
#

I deployed my Express API to Railway and its talking to Redis and Postgres nicely. My client is built in Next 13 with the App Router and is having trouble discovering blackjack.railway.internal:8080

I think this has to do with my binding the Express app to an IPv6 port or at least making it accessible through IPv6 however after a few hours of searching I'm unable to find a clear way of doing this?

client <> server is communicating through ApolloServer.


logger.warn(`Launching in ${process.env.NODE_ENV.toUpperCase()}`);

const schema = makeExecutableSchema({
    typeDefs,
    resolvers: {
        Query,
        Mutation,
        Subscription,
    },
});

const limiter = rateLimit({
    windowMs: 1 * 60 * 1000, // 1 minute
    max: 20,
});

// Create an Express app and HTTP server; attach both the WebSocket
// server and the ApolloServer to this HTTP server.
const app = express();
const httpServer = createServer(app);

// Create WebSocket server using the HTTP server we just set up.
const wsServer = new WebSocketServer({
    server: httpServer,
    path: '/graphql',
});

// Save returned server's info so we can shutdown this server later
const wsServerCleanup = useServer(
    {
        schema,
        context: async (ctx, msg, args) => {
            return { pubsub };
        },
    },
    wsServer
);

// Create ApolloServer.
const server = new ApolloServer({
    schema,
    // just added could cause errors
    csrfPrevention: true,
    plugins: [
        // Proper shutdown for the HTTP server.
        ApolloServerPluginDrainHttpServer({ httpServer }),

        // Proper shutdown for the WebSocket server.
        {
            async serverWillStart() {
                return {
                    async drainServer() {
                        await wsServerCleanup.dispose();
                    },
                };
            },
        },
    ],
});

const main = async () => {
    // Apollo/GraphQL server start.
    await server.start();

    if (server) {
        logger.info(
            `Apollo/GraphQL API is now live on endpoint: ${NODE_PORT}/graphql`
        );
    } else {
        logger.fatal(`Could not start Apollo/GraphQL API`);
        process.exit(1);
    }

    // Middleware for the express application.
    app.use(
        '/graphql',
        cors(),
        helmet(),
        limiter,
        bodyParser.json(),
        expressMiddleware(server, {
            context: async ({ req }) => {
                return { prisma, pubsub, req };
            },
        })
    );
    app.get('/health', (req, res) => {
        res.status(200).send('Okay!');
    });

    const hostname = '::';

    // http server start
    httpServer.listen(NODE_PORT, hostname, () => {
        logger.info(
            `Apollo/GraphQL websocket service is live on endpoint: ${NODE_PORT}/graphql`
        );
    });

    setTimeout(() => {
        pingRedis();
    }, 1000);
};

main();

This is my app.js in my server root. Thanks for any insights.

forest grottoBOT
#

Project ID: N/A

half crownBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

stable cedar
sleek anchor
#

I must be blind, what is NODE_PORT set to?

stable cedar
#

8080

#

Not blind. I left the import statements out

sleek anchor
#

okay and what error do you get when calling that host:port you gave at the top of your message?

stable cedar
#

It errors during build.

Dockerfile


FROM node:21

WORKDIR /app

COPY package*.json ./
COPY package-lock.json package-lock.json 
COPY next.config.js ./

RUN npm ci

COPY . .

RUN npm run build

EXPOSE 3000

CMD [ "npm", "start"]

Error - image

sleek anchor
#

ah, the private network is not available during build

#

you'd have to use the public address during build and then have your app switch to the private address during runtime

stable cedar
#

Interesting. Okay I'll give that a shot.

#

Thanks very much.

#

I'm thinking of doing that address switch using start scripts. Would something like this be a good idea?

"build:production" : "export API_URL=public && next build ..."

"start": "export API_URL=private && next start..."

sleek anchor
#

you'd want to use actual environment variables, but yeah I can see that working

stable cedar
#

Got it. Thank you. I'll see how I might use env vars.

sleek anchor
#

in your service variables add two new variables

API_PRIVATE_URL
API_PUBLIC_URL

set them accordingly with reference variables https://docs.railway.app/develop/variables#railway-provided-variables
specifically using

RAILWAY_PUBLIC_DOMAIN

and

RAILWAY_PRIVATE_DOMAIN

then in your scripts you either do

API_URL=$API_PRIVATE_URL

or

API_URL=$API_PUBLIC_URL
#

tell me the service name of the backend and I'll write the reference variables for you

stable cedar
sleek anchor
#

absolutely, love that attitude

stable cedar
#

Oddly, Next is having trouble pulling in env vars from the service on Railway. I'm triaging that now.

Vars that appear in next.config.js work but calling process.env.[var] doesn't detect any service vars.

#

Variables look OK. I am curious as to what Railway "pre-pends" the URLs with. My web socket services starts with "ws://.." and I want to make sure I account for that

sleek anchor
#

you prefix the reference variables yourself

stable cedar
#

Perfect

sleek anchor
#

so lets see your reference variables

sleek anchor
stable cedar
#

whoops

#

thats old

sleek anchor
#
FROM node:21

# turn off extra external api calls
ENV NPM_CONFIG_UPDATE_NOTIFIER false
ENV NPM_CONFIG_FUND false

# needed to bring this variable into the build
ARG API_PUBLIC_URL

WORKDIR /app

COPY next.config.js package*.json ./

RUN npm ci

COPY . ./

RUN npm run build

EXPOSE 3000

CMD [ "npm", "start"]
sleek anchor
stable cedar
sleek anchor
#

that referances the same services private and public domain, i thought you wanted to reference a different services public and private domains?

stable cedar
#

I probably did a bad job of explaining.

I have an API built with Express that I want my client (Next) to access.

API_PRIVATE_URL and API_PUBLIC_URL above are to connect to the express app from the Next app.

Next vars:

#

Next var raw

sleek anchor
#

oh okay then you did do it right, you where missing the second screenshot for added context

#

well besides the missing scheme at least its right

#

do this on the next vars

http://${{RAILWAY_PRIVATE_DOMAIN}}
stable cedar
#

ah.. add the http:// before the ${{....}} ref?

sleek anchor
#

yep, railway will do the string interpolation

stable cedar
#

thats neat, let me give it a shot

sleek anchor
stable cedar
#

Just updated it, thanks.

sleek anchor
#

hey just wanting to check back in, did you get this working how you wanted?

half crownBOT