SSR环境下Axios请求Strapi报ECONNREFUSED错误,CSR正常
服务器端渲染(SSR)请求Strapi出现ECONNREFUSED错误排查
在SSR场景下请求Strapi时出现连接被拒绝错误,仅在SSR时触发。虽然能看到请求到达Strapi端点且即将返回数据,但最终请求失败,报错为AxiosError: connect ECONNREFUSED ::1:1337。
报错信息
err :>> AxiosError: connect ECONNREFUSED ::1:1337 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1161:16) { port: 1337, address: '::1', syscall: 'connect', code: 'ECONNREFUSED', errno: -4078, config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { Accept: 'application/json, text/plain, */*', 'User-Agent': 'axios/0.27.2' }, baseURL: 'http://localhost:1337', url: '/api/reviews', params: { locale: undefined, populate: '*', sort: 'createdAt:desc' }, method: 'get', data: undefined }, request: <ref *1> Writable { _writableState: WritableState { objectMode: false, highWaterMark: 16384, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: true, defaultEncoding: 'utf8', length: 0, writing: false, corked: 0, sync: true, bufferProcessing: false, onwrite: [Function: bound onwrite], writecb: null, writelen: 0, afterWriteTickInfo: null, buffered: [], bufferedIndex: 0, allBuffers: true, allNoop: true, pendingcb: 0, constructed: true, prefinished: false, errorEmitted: false, emitClose: true, autoDestroy: true, errored: null, closed: false, closeEmitted: false, [Symbol(kOnFinished)]: [] }, _events: [Object: null prototype] { response: [Function: handleResponse], error: [Function: handleRequestError], socket: [Function: handleRequestSocket] }, _eventsCount: 3, _maxListeners: undefined, _options: { maxRedirects: 21, maxBodyLength: 10485760, protocol: 'http:', path: '/api/reviews?populate=*&sort=createdAt:desc', method: 'GET', headers: [Object], agent: undefined, agents: [Object], auth: undefined, hostname: 'localhost', port: '1337', nativeProtocols: [Object], pathname: '/api/reviews', search: '?populate=*&sort=createdAt:desc' }, _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _onNativeResponse: [Function (anonymous)], _currentRequest: ClientRequest { _events: [Object: null prototype], _eventsCount: 7, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: true, chunkedEncoding: false, shouldKeepAlive: false, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: false, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [Socket], _header: 'GET /api/reviews?populate=*&sort=createdAt:desc HTTP/1.1\r\n' + 'Accept: application/json, text/plain, */*\r\n' + 'User-Agent: axios/0.27.2\r\n' + 'Host: localhost:1337\r\n' + 'Connection: close\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'GET', maxHeaderSize: undefined, insecureHTTPParser: undefined, path: '/api/reviews?populate=*&sort=createdAt:desc', _ended: false, res: null, aborted: false, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, reusedSocket: false, host: 'localhost', protocol: 'http:', _redirectable: [Circular *1], [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, _currentUrl: 'http://localhost:1337/api/reviews?populate=*&sort=createdAt:desc', [Symbol(kCapture)]: false } }
请求代码
import { API_URL } from '../config'; import { isJsonString } from '../utils/cookie'; import axios from "axios" export async function GET(ctx) { const { params } = ctx const { lang } = params try { const result = await axios({ baseURL: API_URL, url: '/api/reviews', params: { locale: lang, populate: '*', sort: 'createdAt:desc' } }) console.log('result :>> ', result); return { status: 200, body: result.data, } } catch (err: any) { console.log('err :>> ', err); return { status: 500, body: { error: isJsonString(err.response?.data) || typeof err.response?.data === "object" ? err.response?.data : "DB Error", }, } } }
可能原因分析
- IPv6与IPv4解析冲突:报错显示连接地址是
::1(IPv6的localhost),但Strapi可能仅监听了IPv4的127.0.0.1。SSR环境下Node.js优先解析localhost为IPv6,导致无法连接到只监听IPv4的Strapi服务。 - Strapi服务未完全启动:SSR请求发起时,Strapi可能仍在初始化阶段,虽然端点已存在但还无法处理连接,这种情况在开发环境热重启时常见。
- 端口占用或权限问题:1337端口被其他进程占用,或者SSR进程没有访问该端口的权限(特定环境下可能发生)。
- 网络配置隔离:如果SSR运行在容器(如Docker)中,访问
localhost会指向容器内部而非宿主机的Strapi服务,导致连接失败。
是否与请求头有关?
从报错信息看,请求头仅包含Accept和User-Agent标准字段,无异常内容。ECONNREFUSED是TCP连接层面的错误,发生在HTTP请求发送之前,因此和请求头无关。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

