Next.js Discord

Discord Forum

Access request context next13

Unanswered
Sun bear posted this in #help-forum
Open in Discord
Sun bearOP
Hi!

I learned I cannot user getServerSideProps using next13 new app folder pages etc...
I want to access the context and in particular the request object in order to get the users' IP and fetch its location via geolocation API to first initialize a default city and country for a weather app.

How do I do that?

21 Replies

you can use middleware.ts as follows.

import {NextRequest, NextResponse} from 'next/server'
import countriesJson from '@/app/lib/countries.json'

interface GeoInfo {
    country: string;
    city: string;
    region: string;
}

interface CurrencyDetail {
    name: string;
    symbol: string;
}

interface CountryInfo {
    cca2: string;
    currencies: {
        [key: string]: CurrencyDetail;
    };
    languages: {
        [key: string]: string;
    };
    flag: string;
}


const countryInfoList: any = countriesJson

export const config = {
    matcher: '/',
}

export async function middlewareGeo(req: NextRequest) {
    const {nextUrl: url, geo} = req as { nextUrl: URL, geo: GeoInfo }

    if (!geo || Object.keys(geo).length === 0) {
        console.log("no geo info")
        return
    }

    const country = geo.country
    const city = geo.city
    const region = geo.region

    const countryInfo = countryInfoList.find((x: CountryInfo) => x.cca2 === country)

    let currencyCode = ""
    let currency: CurrencyDetail = {name: "", symbol: ""}
    let languages = ""

    if (countryInfo) {
        const currencies = countryInfo.currencies
        currencyCode = Object.keys(currencies)[0];
        currency = currencies[currencyCode];
        languages = Object.values(countryInfo.languages).join(', ');
    }

    const updatedUrl = new URL(url);

    updatedUrl.searchParams.set('country', country)
    updatedUrl.searchParams.set('city', city)
    updatedUrl.searchParams.set('region', region)

    if (currencyCode) updatedUrl.searchParams.set('currencyCode', currencyCode)
    if (currency.symbol) updatedUrl.searchParams.set('currencySymbol', currency.symbol)
    if (currency.name) updatedUrl.searchParams.set('name', currency.name)
    if (languages) updatedUrl.searchParams.set('languages', languages)

    console.log("updatedUrl", updatedUrl.toString())

    return NextResponse.rewrite(updatedUrl.toString())
}
u need to deploy it on Vercel to get ip right.
Sun bearOP
with this bascially I get a <url>/?<location params> ??
and then get the data from the params?
bascially if I break this down this middleware gets the geo location & redirect (or what?) with planting the geo data in the URL?
@tafutada777
ah got it, it basically proxies the url to be displayed normally in the browser while infact is having the geo parameters sort of hidden to the client. got it.
if you deployed Next.js on Vercel, middleware.ts script is deployed on Cloudflare Woker, which are edge servers located across countries. so it is possible to get precise locations of users(clients)
x-forwarded-for, which is layer 7 HTTP header, are forwarded via reverse-proxy and ISP routers.
but most of ISP hides user's device IP so basically it's ISP IP address that users connect.
Sun bearOP
wow that awesome to know, I didn't know that it basically distributes the middleware script, and thanks I did manage to deploy iit to vercel and got the logs to show my exact location (city, country), and got the demo data so I would be able to work on it in dev environment
you're awesome thanks
i live in Japan, which is a coutry side, but IP is located in Tokyo, it's far away from my home.
Sun bearOP
well I guess it wouldn't be 100% accurate as you said
but for me its actually doing quite a good job
I am stumbling with a error of Headers Overflow because my params are wayyyyyyyyyy to big
I'm trying to pass a big JSON stringified object response from the server as parameter
can I get it into the component in another way rather than just stringify the object and pass it as a param?
middleware is kind like reverse-proxy so it’s just forwarding http requests. so there is the same limit as http requests.
work-around could be Vercel KV, which is Redis key value store, you can store client session info there, then retrieve it from handlers.