Hello Vercel Community,
I’m encountering an issue in my Next.js project where middleware is not being triggered for external API requests from Safaricom’s callback server. Internal API calls and tools like Postman and cURL successfully trigger the middleware and the API route, but the Safaricom callback fails to do so. Here’s the breakdown:
Project Setup
- Framework: Next.js 13 with the
app
directory structure. - Middleware Location:
/src/middleware.ts
- Hosted On: Vercel
- Callback URL:
https://wifi-magement-system.vercel.app/api/stkPushCallback/?Order_ID=${Order_ID}
Middleware Code
Here’s my middleware.ts
file:
import { NextRequest, NextResponse } from 'next/server';
const cors = (req: NextRequest) => {
console.log('CORS middleware triggered for:', req.url);
const allowedOrigins = ['*']; // Currently allowing all origins for testing
const origin = req.headers.get('origin');
const isAllowedOrigin = allowedOrigins.includes(origin || '');
console.log('Request Origin:', origin);
console.log('Is Allowed Origin:', isAllowedOrigin);
const headers: Record<string, string> = {
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Allow-Origin': isAllowedOrigin ? origin || '*' : '*',
'Access-Control-Allow-Credentials': 'true',
};
if (req.method === 'OPTIONS') {
console.log('Handling OPTIONS preflight request');
return new NextResponse(null, {
status: 200,
headers,
});
}
const response = NextResponse.next();
Object.entries(headers).forEach(([key, value]) => {
response.headers.set(key, value);
console.log(`Header Set: ${key} = ${value}`);
});
return response;
};
export function middleware(req: NextRequest) {
console.log('Middleware triggered for:', req.url);
return cors(req);
}
export const config = {
matcher: ['/api/:path*'], // Matches all API routes
};
The Problem
-
Internal Requests Work:
- Middleware is triggered correctly for internal API requests within the project.
- Tools like Postman and cURL successfully trigger the middleware and the API route.
-
External Requests Fail:
- Safaricom’s callback server does not trigger the middleware, and no logs appear from the middleware when the callback is made.
- The callback URL is accessible, confirmed via manual testing with Postman and cURL.
-
Callback Behavior:
- Safaricom successfully sends the STK push callback to the URL, but it seems blocked or ignored by the middleware on Vercel.
What I’ve Tried
- Verified middleware placement (
/src/middleware.ts
) and configuration (matcher: ['/api/:path*']
). - Tested with wildcard origins (
'Access-Control-Allow-Origin': '*'
). - Checked logs to confirm the middleware isn’t triggered for Safaricom callbacks.
- Tested the callback URL with Postman, cURL, and
ngrok
—all work as expected. - Confirmed the Safaricom callback server is not hitting the middleware, even though the endpoint is reachable.
My Questions
- Could Vercel’s infrastructure block certain requests or headers from external servers like Safaricom?
- Is there a specific configuration required to ensure external requests trigger the middleware?
- Are there any known limitations with middleware handling external callbacks in Next.js hosted on Vercel?
Additional Information
- Hosted on Vercel with no custom Vercel configurations for the project.
- Middleware is required to handle CORS preflight and control headers dynamically for external APIs.
Any assistance or guidance on resolving this issue would be greatly appreciated! Thank you for your time and expertise.