微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

调用我的 rest api NextJS 时出现 ETIMEDOUT 错误

如何解决调用我的 rest api NextJS 时出现 ETIMEDOUT 错误

你知道为什么从 axios 调用我的 api 端点会失败

rontend_1  | Error: connect ETIMEDOUT 188.166.224.149:443
frontend_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1142:16) {
frontend_1  |   errno: -110,frontend_1  |   code: 'ETIMEDOUT',frontend_1  |   syscall: 'connect',frontend_1  |   address: '188.166.224.149',frontend_1  |   port: 443,frontend_1  |   config: {
frontend_1  |     url: '/gists',frontend_1  |     method: 'get',frontend_1  |     headers: {
frontend_1  |       Accept: 'application/json,text/plain,*/*',frontend_1  |       'Content-Type': 'application/json',frontend_1  |       'User-Agent': 'axios/0.21.1'
frontend_1  |     },frontend_1  |     baseURL: 'https://api.snippy.blanknodes.com',frontend_1  |     transformRequest: [ [Function: transformRequest] ],frontend_1  |     transformResponse: [ [Function: transformResponse] ],frontend_1  |     timeout: 0,frontend_1  |     withCredentials: true,frontend_1  |     adapter: [Function: httpAdapter],frontend_1  |     xsrfCookieName: 'XSRF-TOKEN',frontend_1  |     xsrfheaderName: 'X-XSRF-TOKEN',frontend_1  |     maxContentLength: -1,frontend_1  |     maxBodyLength: -1,frontend_1  |     validateStatus: [Function: validateStatus],frontend_1  |     data: undefined
frontend_1  |   },frontend_1  |   request: <ref *1> Writable {
frontend_1  |     _writableState: WritableState {
frontend_1  |       objectMode: false,frontend_1  |       highWaterMark: 16384,frontend_1  |       finalCalled: false,frontend_1  |       needDrain: false,frontend_1  |       ending: false,frontend_1  |       ended: false,frontend_1  |       finished: false,frontend_1  |       destroyed: false,frontend_1  |       decodeStrings: true,frontend_1  |       defaultEncoding: 'utf8',frontend_1  |       length: 0,frontend_1  |       writing: false,frontend_1  |       corked: 0,frontend_1  |       sync: true,frontend_1  |       bufferProcessing: false,frontend_1  |       onwrite: [Function: bound onwrite],frontend_1  |       writecb: null,frontend_1  |       writelen: 0,frontend_1  |       afterWriteTickInfo: null,frontend_1  |       buffered: [],frontend_1  |       bufferedindex: 0,frontend_1  |       allBuffers: true,frontend_1  |       allNoop: true,frontend_1  |       pendingcb: 0,frontend_1  |       constructed: true,frontend_1  |       prefinished: false,frontend_1  |       errorEmitted: false,frontend_1  |       emitClose: true,frontend_1  |       autoDestroy: true,frontend_1  |       errored: null,frontend_1  |       closed: false,frontend_1  |       closeEmitted: false,frontend_1  |       [Symbol(kOnFinished)]: []
frontend_1  |     },frontend_1  |     _events: [Object: null prototype] {
frontend_1  |       response: [Function: handleResponse],frontend_1  |       error: [Function: handleRequestError]
frontend_1  |     },frontend_1  |     _eventsCount: 2,frontend_1  |     _maxListeners: undefined,frontend_1  |     _options: {
frontend_1  |       maxRedirects: 21,frontend_1  |       maxBodyLength: 10485760,frontend_1  |       protocol: 'https:',frontend_1  |       path: '/gists',frontend_1  |       method: 'GET',frontend_1  |       headers: [Object],frontend_1  |       agent: undefined,frontend_1  |       agents: [Object],frontend_1  |       auth: undefined,frontend_1  |       hostname: 'api.snippy.blanknodes.com',frontend_1  |       port: null,frontend_1  |       nativeProtocols: [Object],frontend_1  |       pathname: '/gists'
frontend_1  |     },frontend_1  |     _ended: true,frontend_1  |     _ending: true,frontend_1  |     _redirectCount: 0,frontend_1  |     _redirects: [],frontend_1  |     _requestBodyLength: 0,frontend_1  |     _requestBodyBuffers: [],frontend_1  |     _onNativeResponse: [Function (anonymous)],frontend_1  |     _currentRequest: ClientRequest {
frontend_1  |       _events: [Object: null prototype],frontend_1  |       _eventsCount: 7,frontend_1  |       _maxListeners: undefined,frontend_1  |       outputData: [],frontend_1  |       outputSize: 0,frontend_1  |       writable: true,frontend_1  |       _last: true,frontend_1  |       chunkedEncoding: false,frontend_1  |       shouldKeepAlive: false,frontend_1  |       _defaultKeepAlive: true,frontend_1  |       useChunkedEncodingByDefault: false,frontend_1  |       sendDate: false,frontend_1  |       _removedConnection: false,frontend_1  |       _removedContLen: false,frontend_1  |       _removedTE: false,frontend_1  |       _contentLength: 0,frontend_1  |       _hasBody: true,frontend_1  |       _trailer: '',frontend_1  |       finished: true,frontend_1  |       _headerSent: true,frontend_1  |       _closed: false,frontend_1  |       socket: [TLSSocket],frontend_1  |       _header: 'GET /gists HTTP/1.1\r\n' +
frontend_1  |         'Accept: application/json,*/*\r\n' +
frontend_1  |         'Content-Type: application/json\r\n' +
frontend_1  |         'User-Agent: axios/0.21.1\r\n' +
frontend_1  |         'Host: api.snippy.blanknodes.com\r\n' +
frontend_1  |         'Connection: close\r\n' +
frontend_1  |         '\r\n',frontend_1  |       _keepAliveTimeout: 0,frontend_1  |       _onPendingData: [Function: nop],frontend_1  |       agent: [Agent],frontend_1  |       socketPath: undefined,frontend_1  |       maxHeaderSize: undefined,frontend_1  |       insecureHTTPParser: undefined,frontend_1  |       _ended: false,frontend_1  |       res: null,frontend_1  |       aborted: false,frontend_1  |       timeoutCb: null,frontend_1  |       upgradeOrConnect: false,frontend_1  |       parser: null,frontend_1  |       maxHeadersCount: null,frontend_1  |       reusedSocket: false,frontend_1  |       host: 'api.snippy.blanknodes.com',frontend_1  |       _redirectable: [Circular *1],frontend_1  |       [Symbol(kCapture)]: false,frontend_1  |       [Symbol(kNeedDrain)]: false,frontend_1  |       [Symbol(corked)]: 0,frontend_1  |       [Symbol(kOutHeaders)]: [Object: null prototype]
frontend_1  |     },frontend_1  |     _currentUrl: 'https://api.snippy.blanknodes.com/gists',frontend_1  |     [Symbol(kCapture)]: false
frontend_1  |   },frontend_1  |   response: undefined,frontend_1  |   isAxiosError: true,frontend_1  |   toJSON: [Function: toJSON]
frontend_1  | }

当我尝试使用 curl 时,它工作正常。

snippy (main) curl https://api.snippy.blanknodes.com/gists -v
*   Trying 188.166.224.149:443...
* Connected to api.snippy.blanknodes.com (188.166.224.149) port 443 (#0)
* ALPN,offering h2
* ALPN,offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT),TLS handshake,Client hello (1):
* TLSv1.3 (IN),Server hello (2):
* TLSv1.3 (IN),Encrypted Extensions (8):
* TLSv1.3 (IN),Certificate (11):
* TLSv1.3 (IN),CERT verify (15):
* TLSv1.3 (IN),Finished (20):
* TLSv1.3 (OUT),TLS change cipher,Change cipher spec (1):
* TLSv1.3 (OUT),Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN,server accepted to use h2
* Server certificate:
*  subject: CN=api.snippy.blanknodes.com
*  start date: Jul 22 01:09:00 2021 GMT
*  expire date: Oct 20 01:08:58 2021 GMT
*  subjectAltName: host "api.snippy.blanknodes.com" matched cert's "api.snippy.blanknodes.com"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2,server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5641a162d970)
> GET /gists HTTP/2
> Host: api.snippy.blanknodes.com
> user-agent: curl/7.77.0
> accept: */*
> 
* TLSv1.3 (IN),Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200 
< access-control-allow-credentials: true
< content-security-policy: default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
< content-type: application/json; charset=utf-8
< date: Thu,22 Jul 2021 03:07:51 GMT
< etag: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
< expect-ct: max-age=0
< referrer-policy: no-referrer
< server: Caddy
< strict-transport-security: max-age=15552000; includeSubDomains
< vary: Origin
< x-content-type-options: nosniff
< x-dns-prefetch-control: off
< x-download-options: noopen
< x-frame-options: SAMEORIGIN
< x-permitted-cross-domain-policies: none
< x-xss-protection: 0
< content-length: 2
< 
* Connection #0 to host api.snippy.blanknodes.com left intact
[]

此应用使用 docker-compose 和 caddy 服务器运行。

我使用 caddy 进行反向代理和自动 https

{
   email [REDACTED]
   acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

snippy.blanknodes.com {
  reverse_proxy frontend:3000
}

api.snippy.blanknodes.com {
  reverse_proxy backend:4000
}

并通过 docker-compose up

运行应用程序
version: "3.7"
services:
  database:
    image: postgres:13-alpine
    restart: always
    environment:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      APP_DB_NAME: snippy_prod
      APP_DB_USER: jeepers3327
    volumes:
      - ./db:/docker-entrypoint-initdb.d/
      - postgres_data:/var/lib/postgresql/data/
    expose: 
      - 5432
    networks: 
      - webserver

  sessions:
    image: redis:6.2-alpine
    volumes:
      - redis_data:/redis/data
    ports:
      - 6379
    networks: 
      - webserver

  backend:
    build: ./backend
    restart: unless-stopped
    env_file: ./backend/.env.production
    depends_on:
      - database
      - sessions
    networks: 
      - webserver

  frontend:
    build: ./frontend
    restart: unless-stopped
    depends_on:
      - backend
    networks: 
      - webserver
      
  proxy:
    image: caddy:2.4.3-alpine
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    volumes:
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on: 
      - backend
      - frontend
    networks: 
      - webserver

volumes:
  redis_data:
  postgres_data:
  caddy_data:
  caddy_config:

networks: 
  webserver:
    external: true

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。