Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions app/[store]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client'

import { useParams } from 'next/navigation'

export default function StorePage() {
const params = useParams()
const store = params.store

return (
<div>
<h1>Tienda: {store}</h1>
</div>
)
}
45 changes: 37 additions & 8 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,42 @@ import { handleCollectionOwnershipMiddleware } from './middlewares/ownership/col

export async function middleware(request: NextRequest) {
const path = request.nextUrl.pathname
const hostname = request.headers.get('host') || ''
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate the hostname to prevent header spoofing.

The hostname is retrieved directly from request headers without validation, which could be manipulated by clients. This poses a security risk as attackers could potentially bypass subdomain-based access controls.

Apply this diff to add hostname validation:

-  const hostname = request.headers.get('host') || ''
+  const hostname = request.headers.get('host') || ''
+  
+  // Validate hostname to prevent header spoofing
+  const allowedDomains = isProduction 
+    ? ['fasttify.com'] 
+    : ['localhost']
+  
+  const isValidHostname = allowedDomains.some(domain => 
+    hostname === domain || hostname.endsWith(`.${domain}`)
+  )
+  
+  if (!isValidHostname) {
+    return NextResponse.redirect(new URL('/', request.url))
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hostname = request.headers.get('host') || ''
const hostname = request.headers.get('host') || ''
// Validate hostname to prevent header spoofing
const allowedDomains = isProduction
? ['fasttify.com']
: ['localhost']
const isValidHostname = allowedDomains.some(domain =>
hostname === domain || hostname.endsWith(`.${domain}`)
)
if (!isValidHostname) {
return NextResponse.redirect(new URL('/', request.url))
}
🤖 Prompt for AI Agents
In middleware.ts at line 11, the hostname is obtained directly from request
headers without validation, which risks header spoofing. To fix this, validate
the hostname against a whitelist of allowed hostnames or use a robust parsing
method to ensure it matches expected patterns before using it for any access
control decisions. Reject or handle requests with invalid or unexpected
hostnames appropriately to prevent security bypass.


// Configuración de dominios
const isProduction = process.env.NODE_ENV === 'production'

// Detectar subdominios
let subdomain = ''
if (isProduction) {
// En producción: verificar si hay un subdominio (ej: tienda.fasttify.com)
const allowedDomains = ['fasttify.com', 'www.fasttify.com'];
const parts = hostname.split('.');
const domain = parts.slice(-2).join('.');
if (parts.length > 2 && allowedDomains.includes(domain)) {
subdomain = parts[0];
}
} else {
// En desarrollo: usar el formato subdominio.localhost:3000 o localhost:3000
if (hostname.includes('.localhost')) {
subdomain = hostname.split('.')[0]
}
}

// Si hay un subdominio y estamos en la raíz, reescribir a la ruta de la tienda
if (subdomain && subdomain !== 'www' && path === '/') {
// Reescribir la URL para mostrar la página de la tienda
const url = request.nextUrl.clone()
url.pathname = `/${subdomain}`
return NextResponse.rewrite(url)
}

// Si hay un subdominio y la ruta no empieza con el subdominio, agregar el prefijo
if (subdomain && subdomain !== 'www' && !path.startsWith(`/${subdomain}`)) {
const url = request.nextUrl.clone()
url.pathname = `/${subdomain}${path}`
return NextResponse.rewrite(url)
}
Comment on lines +33 to +46
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consolidate URL rewriting logic to eliminate duplication.

Both conditional blocks check for subdomain existence and perform similar URL rewriting. This can be simplified into a single block.

Apply this diff to consolidate the logic:

-  // Si hay un subdominio y estamos en la raíz, reescribir a la ruta de la tienda
-  if (subdomain && subdomain !== 'www' && path === '/') {
-    // Reescribir la URL para mostrar la página de la tienda
-    const url = request.nextUrl.clone()
-    url.pathname = `/${subdomain}`
-    return NextResponse.rewrite(url)
-  }
-
-  // Si hay un subdominio y la ruta no empieza con el subdominio, agregar el prefijo
-  if (subdomain && subdomain !== 'www' && !path.startsWith(`/${subdomain}`)) {
-    const url = request.nextUrl.clone()
-    url.pathname = `/${subdomain}${path}`
-    return NextResponse.rewrite(url)
-  }
+  // Reescribir URLs basadas en subdominios
+  if (subdomain && subdomain !== 'www') {
+    const url = request.nextUrl.clone()
+    
+    if (path === '/') {
+      // Si estamos en la raíz, reescribir a la ruta de la tienda
+      url.pathname = `/${subdomain}`
+    } else if (!path.startsWith(`/${subdomain}`)) {
+      // Si la ruta no empieza con el subdominio, agregar el prefijo
+      url.pathname = `/${subdomain}${path}`
+    } else {
+      // La ruta ya tiene el prefijo correcto
+      return NextResponse.next()
+    }
+    
+    return NextResponse.rewrite(url)
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Si hay un subdominio y estamos en la raíz, reescribir a la ruta de la tienda
if (subdomain && subdomain !== 'www' && path === '/') {
// Reescribir la URL para mostrar la página de la tienda
const url = request.nextUrl.clone()
url.pathname = `/${subdomain}`
return NextResponse.rewrite(url)
}
// Si hay un subdominio y la ruta no empieza con el subdominio, agregar el prefijo
if (subdomain && subdomain !== 'www' && !path.startsWith(`/${subdomain}`)) {
const url = request.nextUrl.clone()
url.pathname = `/${subdomain}${path}`
return NextResponse.rewrite(url)
}
// Reescribir URLs basadas en subdominios
if (subdomain && subdomain !== 'www') {
const url = request.nextUrl.clone()
if (path === '/') {
// Si estamos en la raíz, reescribir a la ruta de la tienda
url.pathname = `/${subdomain}`
} else if (!path.startsWith(`/${subdomain}`)) {
// Si la ruta no empieza con el subdominio, agregar el prefijo
url.pathname = `/${subdomain}${path}`
} else {
// La ruta ya tiene el prefijo correcto
return NextResponse.next()
}
return NextResponse.rewrite(url)
}
🤖 Prompt for AI Agents
In middleware.ts around lines 31 to 44, the URL rewriting logic for subdomains
is duplicated in two separate if blocks. Consolidate these by combining the
conditions that check for subdomain existence and rewrite the URL accordingly in
a single block. Use a single cloned URL object and adjust the pathname based on
whether the current path is '/' or does not start with the subdomain prefix,
then return the rewritten response once.


// Verificar propiedad de productos específicos
if (
Expand Down Expand Up @@ -45,12 +81,5 @@ export async function middleware(request: NextRequest) {
}

export const config = {
matcher: [
'/subscription-success',
'/account-settings',
'/first-steps',
'/my-store',
'/login',
'/store/:path*',
],
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
}