How the Nitro Server-Side Proxy Handles WeChat API Requests

The Nitro server-side proxy acts as a secure intermediary by forwarding client requests to WeChat MP endpoints with forged headers, managing authentication cookies via an LRU-backed store, and sanitizing responses to prevent CORS issues.

The wechat-article/wechat-article-exporter repository leverages Nuxt 3's Nitro engine to circumvent browser restrictions when interfacing with the WeChat public platform (MP). All WeChat API calls flow through a dedicated server-side proxy that normalizes headers, maintains authentication state, and cleans response cookies before they reach the client.

Request Flow Architecture

The proxy implementation centers on the proxyMpRequest() function defined in [server/utils/proxy-request.ts](https://github.com/wechat-article/wechat-article-exporter/blob/master/server/utils/proxy-request.ts). When the front-end invokes a Nitro API route (e.g., server/api/web/mp/...), execution passes through this utility, which orchestrates header preparation, cookie retrieval, and response sanitization.

Header Preparation and Security

Inside proxyMpRequest, the function constructs a Headers object mandatory for WeChat acceptance:

These headers are applied to a native Request object before forwarding.

The proxy retrieves stored credentials through getCookieFromStore in [server/utils/CookieStore.ts](https://github.com/wechat-article/wechat-article-exporter/blob/master/server/utils/CookieStore.ts). The logic branches based on the incoming request:

  • If the caller explicitly provides a cookie value in the options object, that string is used directly
  • Otherwise, the utility inspects the X-Auth-Key header or auth-key cookie, then fetches the associated AccountCookie from either an in-memory LRU cache or the persistent KV store

The resulting cookie string is attached to the outgoing request, allowing the proxy to impersonate a logged-in browser session.

Request Construction and Forwarding

For POST requests, the proxy URL-encodes the body as application/x-www-form-urlencoded before constructing the final Request instance. The endpoint URL may be extended with query parameters supplied via options.query. When the environment variable NUXT_DEBUG_MP_REQUEST is set, the fully formed request is logged for debugging.

Because the proxy executes on the server, it uses fetch() to communicate with WeChat endpoints without triggering browser CORS preflight checks or cookie restrictions.

Response Processing and Action Handlers

After receiving the WeChat response, the proxy executes action-specific logic based on options.action:

  • start_login – Extracts the temporary uuid cookie set by the WeChat login page
  • login – Parses the JSON body to extract redirect_url, retrieves the token parameter, and persists the complete cookie set via cookieStore.setCookie. It returns two Set-Cookie headers to the client: a new auth-key (4-day expiry) and an expired uuid to clear the temporary session
  • switch_account – Appends a switch_account=1 cookie to signal account context changes

The proxy strips all original Set-Cookie headers from WeChat to prevent client-side exposure, injecting only the sanitized proxy-managed cookies.

The CookieStore utility maintains state through an LRU-style in-memory Map<string, AccountCookie> backed by a KV storage layer (server/kv/cookie.ts).

Each AccountCookie instance parses raw Set-Cookie strings into structured CookieEntity objects and can serialize them back into HTTP-ready header strings via the toString() method. When setCookie is invoked, the update is written to both the in-memory cache for immediate subsequent lookups and the KV store for persistence across server restarts.

Practical Implementation Examples

The following patterns demonstrate how to invoke the proxy within Nitro API routes:

// server/api/articles/list.get.ts
import { proxyMpRequest } from '@/server/utils/proxy-request';

export default defineEventHandler(async (event) => {
  const authKey = getCookie(event, 'auth-key');
  
  return proxyMpRequest({
    endpoint: 'https://mp.weixin.qq.com/cgi-bin/home',
    method: 'GET',
    action: 'fetch_articles',
    query: { t: 'home/index', lang: 'zh_CN' },
    cookie: undefined, // pulled automatically from store via authKey
    event,
    parseJson: true,
  });
});
// server/api/auth/login.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  
  return proxyMpRequest({
    endpoint: 'https://mp.weixin.qq.com/cgi-bin/login',
    method: 'POST',
    action: 'login',
    body: { username: body.user, pwd: body.pass },
    event,
    parseJson: false, // returns redirect URL in body
  });
});

Summary

  • CORS Bypass: The Nitro server-side proxy executes requests outside browser constraints, eliminating preflight issues when contacting mp.weixin.qq.com
  • Header Forgery: Fixed Referer, Origin, and User-Agent headers convince WeChat servers the request originates from an official domain
  • Authentication Management: The CookieStore utility persists sessions via an LRU cache backed by KV storage, keyed by auth-key tokens
  • Login Flow Support: Special actions (start_login, login) handle UUID extraction, token parsing from redirect_url, and cookie rotation
  • Security Sanitization: Original WeChat Set-Cookie headers are stripped and replaced with proxy-controlled equivalents to prevent credential leakage

Frequently Asked Questions

Why does the proxy need to spoof Referer and Origin headers?

WeChat's MP platform validates the source of incoming requests to prevent CSRF and unauthorized scraping. By setting both Referer and Origin to https://mp.weixin.qq.com/, the Nitro server-side proxy satisfies these security checks, allowing the API to accept the request as if it came from an authenticated browser session on the official domain.

How does the CookieStore handle session persistence across server restarts?

The CookieStore maintains a hot in-memory Map for low-latency lookups during active requests, but delegates long-term storage to a KV backend defined in server/kv/cookie.ts. When setCookie is called, the utility writes to both layers simultaneously, ensuring that even if the Nitro process restarts, the auth-key can still retrieve the associated AccountCookie from persistent storage.

What is the difference between the uuid and auth-key cookies?

The uuid cookie is a temporary identifier generated during the start_login phase that tracks the initial login session on WeChat's servers. Upon successful authentication (login action), the proxy exchanges this temporary cookie for a permanent session identified by auth-key, which is stored in the CookieStore and valid for four days. The proxy then instructs the client to expire the uuid cookie since it is no longer needed.

Why must Accept-Encoding be set to identity instead of allowing compression?

The proxy disables compression by forcing Accept-Encoding: identity because the Nitro server needs to potentially clone and inspect the response body before forwarding it to the client. Compressed responses (gzip/deflate) can only be read once and cannot be trivially cloned for logging or JSON parsing without consuming the stream, which would break subsequent transmission to the client.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →