[SOLVED] How to get the requested hostname in the context of ApolloServer

Configure the local /etc/hosts file to make the domain name point to 127.0.0.1

127.0.0.1 hello.com

Then start the ApolloServer application, the middleware uses express

The req.headers.host of ApolloServer gets the host of the server, which is localhost:4000, and what I input in the browser is hello.com:4000,

image

import { ApolloServer, makeExecutableSchema } from 'apollo-server-express';
import { WebApp } from 'meteor/webapp';
import typeDefs from './type';
import resolvers from './resolver';

const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
  resolverValidationOptions: { requireResolversForResolveType: false },
});

const server = new ApolloServer({
  schema,
  context: async ctx => {
    console.log(ctx.req.headers);
    return ctx;
  },
});

server.applyMiddleware({
  app: WebApp.connectHandlers,
  path: '/graphql'
});

I20210203-13:20:31.667(8)? {
I20210203-13:20:31.667(8)?   'x-forwarded-host': 'localhost:4000',
I20210203-13:20:31.668(8)?   'x-forwarded-proto': 'http',
I20210203-13:20:31.668(8)?   'x-forwarded-port': '4000',
I20210203-13:20:31.668(8)?   'x-forwarded-for': '127.0.0.1',
I20210203-13:20:31.668(8)?   host: 'localhost:4000',
I20210203-13:20:31.668(8)?   connection: 'close',
I20210203-13:20:31.668(8)?   'accept-encoding': 'gzip,deflate',
I20210203-13:20:31.668(8)?   'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
I20210203-13:20:31.669(8)?   'content-length': '256',
I20210203-13:20:31.669(8)?   clientsidehostname: 'http://localhost:4000/',
I20210203-13:20:31.669(8)?   'content-type': 'application/json',
I20210203-13:20:31.669(8)?   accept: '*/*'
I20210203-13:20:31.669(8)? }
I20210203-13:20:31.744(8)? f

Only the server’s headers are obtained
How to obtain the client’s headers parameter?

So how can I get hello.com:4000,
or give me a hint, which direction should I look for?

Any suggestions, please help

Is there any magic way to do this, :anger:

configure nginx?
Via webapp?
Apollo itself can do it?

I really want to know :roll_eyes:

you need to set the ROOT_URL environment variable to : hello.com

Thanks for your reply. What I want to get is the URL entered by the user in the browser, which may not be the same domain name as ROOT_URL, because an application can bind to many domain names, thank you :crazy_face:

Any other thoughts?Online etc. :pray:

in your ApolloClient config you can use the HttpLink header section as such :

new HttpLink({
    headers: { dn: window.location.hostname },
    uri: 'your gql uri',
    credentials: 'same-origin',
    fetch: fetchFunction
  })
1 Like

This Httplink is running on the server, there is no way to get the properties of the window object, am I wrong? :roll_eyes:

By the way, I used the GitHub-Gorbus / meteor-react-apollo-ssr you released last time. You should be familiar with it. Can you get it? By the way, your example is really great, and it made me realize the magic of apollo again :partying_face:

just do

{ dn: Meteor.isServer ? Meteor.absoluteUrl('/') : window.location.hostname }

instead of { dn: window.location.hostname }

Sorry, but I still didn’t succeed. The code is still running on the client and the server has no way to get it.

/imports/both

import {Meteor} from "meteor/meteor";
import {ApolloClient, InMemoryCache, createHttpLink} from "@apollo/client";
import fetch from "cross-fetch";

const cache = Meteor.isClient
   ? new InMemoryCache().restore(window.__APOLLO_STATE__)
   : new InMemoryCache();

const httpLink = {
   uri: Meteor.absoluteUrl('/graphql'),
   headers: {
       clientHostname: Meteor.isServer ? Meteor.absoluteUrl('/') : window.location.hostname,
       fixedField: 'hello world'
   },
   fetch}

export default apolloClient = new ApolloClient({
   ssrMode: Meteor.isServer,
   link: createHttpLink(httpLink),
   cache,
   ssrForceFetchDelay: 100,
})


/server/apollo.js

const resolvers = {
    Query: {
        getLink: (obj, {id}) => {
            return LinksCollection.findOne(id);
        },
        getLinks: (obj, {}, {params}) => {
            console.log(params);
            return LinksCollection.find().fetch();
        },
    },
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context: async ({req}) => {
        req.params = {
            clienthostname: req.headers.clienthostname,
            fixedField: req.headers.fixedfield,
        }
        return req;
    }
});

server.applyMiddleware({
    app: WebApp.connectHandlers,
    cors: true,
});

Edit the /etc/hosts file

127.0.0.1 hello.com

Try to access in the browser

http://hello.com:3000

Then the output is still not successful

{ clienthostname: 'http://localhost:3000/', fixedField: 'hello world' }

The example based on meteor-react-apollo-ssr did not work
repo

Keep waiting, online, etc

@nschwarz
This is my code

headers: {
        clientHostname: Meteor.isServer ? 'hello_world' : window.location.hostname,
    },

The result is this, is there any way? :roll_eyes:

Note the custom field clienthostname

headers: {
I20210206-16:54:36.530(8)?       'x-forwarded-host': 'localhost:5000',
I20210206-16:54:36.530(8)?       'x-forwarded-proto': 'http',
I20210206-16:54:36.530(8)?       'x-forwarded-port': '5000',
I20210206-16:54:36.531(8)?       'x-forwarded-for': '127.0.0.1',
I20210206-16:54:36.531(8)?       host: 'localhost:5000',
I20210206-16:54:36.531(8)?       connection: 'close',
I20210206-16:54:36.531(8)?       'accept-encoding': 'gzip,deflate',
I20210206-16:54:36.531(8)?       'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
I20210206-16:54:36.531(8)?       'content-length': '288',
I20210206-16:54:36.531(8)?       clienthostname: 'hello_wolrd',
I20210206-16:54:36.531(8)?       'content-type': 'application/json',
I20210206-16:54:36.532(8)?       accept: '*/*'
I20210206-16:54:36.532(8)?     },

The server can only get the data of the server, there is no way to get the data of the client

Yes because you’re using SSR as “SERVER SIDE rendering” so the first request is obviously made on the server…

if you want to get the domain on the original request on the server, you should get it through the sink.request.headers object in onPageLoad, pass it down in the Client constructor, then do :
{ clientHostname: Meteor.isServer ? my_param : window.location.hostname }

I don’t know how to pass the sink.request.headers.host obtained in onPageLoad to the headers in the client.

This is my code

import { Meteor } from "meteor/meteor";
import { ApolloClient, InMemoryCache, HttpLink, createHttpLink } from "@apollo/client";
import fetch from "cross-fetch";
import {Accounts} from "meteor/accounts-base";
import {onPageLoad} from "meteor/server-render";

const cache = Meteor.isClient
  ? new InMemoryCache().restore(window.__APOLLO_STATE__)
  : new InMemoryCache();

let param = 'abc';
onPageLoad( sink => {
    console.log('onPageLoad: ',sink.request?.headers?.host);
    param = sink.request?.headers?.host;
});

// http
const httpLink = new HttpLink({
    uri: Meteor.absoluteUrl('/graphql'),
    headers: {
        authorization: Meteor.isClient ? Accounts._storedLoginToken() : '',
        clientHostname: Meteor.isServer ? param : window.location.hostname,
    },
    fetch
})

//createHttpLink({ uri: Meteor.absoluteUrl('/graphql'), fetch })
const client = new ApolloClient({
  ssrMode: Meteor.isServer,
  link: httpLink,
  cache,
  ssrForceFetchDelay: 100,
})

export default client

Output result

I20210207-12:24:06.540(8)? onPageLoad:  hello.com:3000
I20210207-12:24:06.582(8)? {
I20210207-12:24:06.582(8)?   'x-forwarded-host': 'localhost:3000',
I20210207-12:24:06.582(8)?   'x-forwarded-proto': 'http',
I20210207-12:24:06.583(8)?   'x-forwarded-port': '3000',
I20210207-12:24:06.583(8)?   'x-forwarded-for': '127.0.0.1',
I20210207-12:24:06.583(8)?   host: 'localhost:3000',
I20210207-12:24:06.583(8)?   connection: 'close',
I20210207-12:24:06.583(8)?   'accept-encoding': 'gzip,deflate',
I20210207-12:24:06.583(8)?   'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
I20210207-12:24:06.583(8)?   'content-length': '120',
I20210207-12:24:06.584(8)?   clienthostname: 'abc',
I20210207-12:24:06.584(8)?   authorization: '',
I20210207-12:24:06.584(8)?   'content-type': 'application/json',
I20210207-12:24:06.584(8)?   accept: '*/*'
I20210207-12:24:06.584(8)? }

It may be clearer to describe with pictures, I don’t know if the idea is wrong, it doesn’t feel so simple

image

@nschwarz I solved it, thank you for your help,you’
re right :+1: