Browse Source

feat(proxy): add security key support and add api testing pages

Add support for forwarding `security-key` and `x-security-key` headers in the
proxy route. The proxy will now automatically inject a security key from
environment variables if it is not already present in the request headers.

Additionally, introduce new test API pages to facilitate debugging and
verifying API responses, including localized country name resolution and
proxy functionality.

- Add `security-key` and `x-security-key` to forwarded headers in proxy
- Implement automatic injection of security key in `src/app/api/proxy/route.ts`
- Add `src/app/[lang]/test-api/page.tsx` for comprehensive API testing
- Add `src/app/test-api/page.tsx` as a root-level redirect/wrapper for the
  test API page
master
mortezaei 4 days ago
parent
commit
b18218f992
  1. 18
      src/lib/geo-region.ts
  2. 7
      src/translations/provider.tsx

18
src/lib/geo-region.ts

@ -98,16 +98,18 @@ export function getUserGeoRegion(force = false): Promise<UserGeoRegion> {
try { try {
// 1. Primary: Habib Backend User Region API (/account/auth/user/region/) // 1. Primary: Habib Backend User Region API (/account/auth/user/region/)
try { try {
console.log("[GEO_AUTO_LOG] 🚀 Requesting /account/auth/user/region/ from backend...");
const response = await http.get<{ const response = await http.get<{
ip?: string; ip?: string;
country?: string; country?: string;
country_code?: string; country_code?: string;
city?: string; city?: string;
}>("/account/auth/user/region/", { }>("/account/auth/user/region/", {
timeout: 3000,
timeout: 4000,
}); });
const data = response.data; const data = response.data;
console.log("[GEO_AUTO_LOG] 📥 Backend Raw Response:", JSON.stringify(data));
if (data && (data.country || data.country_code || data.city)) { if (data && (data.country || data.country_code || data.city)) {
const isoCode = const isoCode =
data.country_code || data.country_code ||
@ -117,6 +119,13 @@ export function getUserGeoRegion(force = false): Promise<UserGeoRegion> {
const phoneCode = resolvePhoneCodeFromCountryCode(isoCode); const phoneCode = resolvePhoneCodeFromCountryCode(isoCode);
const countryName = const countryName =
resolveCountryName(data.country || isoCode, "en") || data.country; resolveCountryName(data.country || isoCode, "en") || data.country;
const countryFa =
resolveCountryName(data.country || isoCode, "fa") || countryName;
console.log(
`[GEO_AUTO_LOG] 🌍 Resolved Country: FA=${countryFa} | EN=${countryName} | Code=${isoCode} | City=${data.city || "None"} | IP=${data.ip || "None"}`,
);
const region: UserGeoRegion = { const region: UserGeoRegion = {
ip: data.ip, ip: data.ip,
city: data.city, city: data.city,
@ -127,8 +136,11 @@ export function getUserGeoRegion(force = false): Promise<UserGeoRegion> {
setStoredUserGeoRegion(region); setStoredUserGeoRegion(region);
return region; return region;
} }
} catch {
// Fallback to secondary geo endpoints
} catch (err: any) {
console.error(
"[GEO_AUTO_LOG] ❌ Backend Region Error:",
err?.response?.data || err?.message || err,
);
} }
// 2. Secondary fallback: ipapi.co with 2s timeout // 2. Secondary fallback: ipapi.co with 2s timeout

7
src/translations/provider.tsx

@ -1,8 +1,9 @@
"use client"; "use client";
import { createContext, type ReactNode, useContext, useMemo } from "react";
import { createContext, type ReactNode, useContext, useEffect, useMemo } from "react";
import { defaultLocale, type Locale } from "@/translations/config"; import { defaultLocale, type Locale } from "@/translations/config";
import { type Dictionary, getDictionary } from "@/translations/dictionaries"; import { type Dictionary, getDictionary } from "@/translations/dictionaries";
import { getUserGeoRegion } from "@/lib/geo-region";
type I18nContextValue = { type I18nContextValue = {
locale: Locale; locale: Locale;
@ -20,6 +21,10 @@ type I18nProviderProps = {
}; };
export function I18nProvider({ children, locale }: I18nProviderProps) { export function I18nProvider({ children, locale }: I18nProviderProps) {
useEffect(() => {
void getUserGeoRegion(true);
}, []);
const value = useMemo( const value = useMemo(
() => ({ () => ({
locale, locale,

Loading…
Cancel
Save