background

Now many websites are using a separate architecture of the front and back end, the front and back end can not be on the same server, the front end to ensure SEO, must use pre-rendering, SSG or SSR technology. My site uses the SSR technology of NextJS. When a page is pre-rendered on the renderer side, an Axios instance is first called to request the interface. But there’s a problem. The header of the request on the renderer side is always the User Agent and IP of the renderer side, and the metadata of the User itself cannot be retrieved. Obviously, this is not what we want to get first. Of course, this only happens on the first visit.
To solve this problem, you must find a way to forward the original request header or other metadata to the request. It’s a bit like a reverse proxy, but a bit different. The good news is that NextJS provides this interface.

Hit the pit

With that in mind, I stepped in a lot of holes.
First I looked up that NextJS can be defined on the Custom App
getInitialProps(Consistent with NextPage). But it takes one argument of type
AppContextLocated in the
next/appIn the package.
getInitialPropsAn object must be returned, but because it is Root Component. All Children props must be accepted and then returned. The good news is that NextJS provides us with a way to build a base by simply doing the following.
app.getInitialProps = async (props: AppContext) => {
   const appProps = await App.getInitialProps(props);
	 return { ...appProps }
}Copy the code
Then we need to expand.
The first thing we need to know
propsThere’s one on
ctxThe object,
ctxOne of the
reqObject of type
IncomingMessage. this
reqThe object is the user’s request, we just need to put this
reqSome metadata is appended to a later request
axiosFor example. Of course, you only need to determine whether it is in the pre-render, because if it is not in the render side, there is no need to do forwarding.
We can use
typeof window === 'undefined'To see if it’s on the render side.
export const isClientSide = () => {
  returntypeof window ! = ='undefined'
}
export const isServerSide = () => {
  return! isClientSide() }Copy the code
The next step is to get the real IP address of the user. If you are using Nginx or other server software to reverse generation, you will usually attach the real IP address to the Headers.
const getRealIP = (request: IncomingMessage) => {
   let ip =
      ((request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress) as string) || undefined
    if (ip && ip.split(', ').length > 0) {
      ip = ip.split(', ')[0]
    }
	 return ip
}Copy the code
And then how to attach it to Axios. There’s a pit here,
Don’t attach axios.default. headers directly, because it looks like it will work (and it will only work in dev), but production immediately dies
We can attach to an Axios instance. Directly in the
service.default.headers.commonAssign to the key.
import Package from 'package.json'
import service from '.. /utils/request'
import { isServerSide } from '.. /utils'
import App, { AppContext } from 'next/app'

app.getInitialProps = async (props: AppContext) => {
  const appProps = await App.getInitialProps(props)

  const ctx = props.ctx
  const request = ctx.req

  if (request && isServerSide()) {
    let ip =
      ((request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress) as string) || undefined
    if (ip && ip.split(', ').length > 0) {
      ip = ip.split(', ')[0]
    }
    service.defaults.headers.common['x-forwarded-for'] = ip

    service.defaults.headers.common['User-Agent'] =
      request.headers['user-agent'] +
      ' mx-space render server' +
      `/v${Package.version}`}return { ...appProps }
}Copy the code
And getting UA is easy, straight forward
request.headers['user-agent']You can get it.
That’s the complete code.