Add hostname
parameter in ctx
which returns current hostname on both server and client.
We have 2 web apps - Next.js frontend and Django API. We use Nginx to proxy routes so both are using the same host but API is hosted under /api
. And because we deliver our app to VPS we don't know the current host so we can't just use localhost
.
I have to use custom _app without prerendering so my page only renders on server.
Here's my _app:
import React from 'react'
import App from 'next/app'
class CustomApp extends App {
static async getInitialProps({ Component, ctx }) {
let host
if (ctx.req) {
host = ctx.req.headers.host
} else {
host = location.hostname
}
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ ...ctx, host })
}
return { pageProps }
}
render() {
const { Component, pageProps } = this.props
return <Component {...pageProps} />
}
}
export default CustomApp
I can make a PR with this custom getInitialProps
argument so it will be accessible via ctx.hostname
:
Page.getInitialProps = async ({ hostname }) => {
const res = await fetch(`${hostname}/some-proxied-api/data`)
}
Write a function getHost
and call it in every getInitialProps
. Not very suitable especially when you have tons of pages with using getInitialProps
.
This is unnecessary and can be handled by creating your own fetch wrapper. We typically don't increase the API surface for features easily/better handled in user-land.
Thanks for the suggestion!
By the way, you don't need hostname on the client.
This should be sufficient:
fetch(`${req ? req.headers.host : ''}/some-proxied-api/data`)
You can subscribe to https://github.com/zeit/next.js/pull/7300 and we'll post there if we ever revive that feature, but the tl;dr is to allow fetch('/bla')
to "just work" on the server as it does on the client.
This is unnecessary and can be handled by creating your own fetch wrapper. We typically don't increase the API surface for features easily/better handled in user-land.
Thanks for the suggestion!
By the way, you don't need hostname on the client.
This should be sufficient:
fetch(`${req ? req.headers.host : ''}/some-proxied-api/data`)
But I still can't use getInitialProps
in _app with CSR, right? so I have to write this every time. Although, nice suggestion :+1:
Yes, you need to write it once for each page. This will be better as your application naturally evolves and maybe short-circuits the HTTP API and uses a direct code call or similar.
Note that req.headers.host
is not always safe and can be spoofed when hosting yourself. Many platforms override it to be consistent with say a deployment url, hence why we can't provide it just like that, as it would introduce potential security issues for a subset of users.
May I suggest reviving this? ctx.hostname
appears to me as the only way to retrieve the hostname inside getInitialProps
when ctx.req
does not exist because the user followed a <Link>
. Another way of passing info to getInitialProps
such as a ctx.state
could be an alternative too.
If I actually didn't see a way of doing this that already exists, please let me know.
Most helpful comment
May I suggest reviving this?
ctx.hostname
appears to me as the only way to retrieve the hostname insidegetInitialProps
whenctx.req
does not exist because the user followed a<Link>
. Another way of passing info togetInitialProps
such as actx.state
could be an alternative too.If I actually didn't see a way of doing this that already exists, please let me know.