http-proxy-middleware: [Bug] not working at node 17

Checks

Describe the bug (be clear and concise)

use the library to proxy into another service. not working when upgraded to node 17.

Step-by-step reproduction instructions

1. using node 14.17 - works.
2. replace node 17.x - doesn't work.

console error:

[HPM] Error occurred while proxying request localhost:3000/aaa/ to http://localhost:3001/ [ECONNREFUSED] 


### Expected behavior (be clear and concise)

proxy should work and return the data from another proxied service

### How is http-proxy-middleware used in your project?

```shell
└── http-proxy-middleware@2.0.2

What http-proxy-middleware configuration are you using?

{
    target,
    changeOrigin: true,
    headers: {
      tenant,
    },
  }

What OS/version and node/version are you seeing the problem?

System:
    OS: macOS 12.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 492.53 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 17.4.0 - ~/.nvm/versions/node/v17.4.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 8.3.1 - ~/.nvm/versions/node/v17.4.0/bin/npm
    Watchman: 2021.10.18.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.10.1 - /Users/XXX/.rvm/rubies/ruby-head/bin/pod
    Homebrew: 3.3.9 - /usr/local/bin/brew
    pip3: 21.2.4 - /usr/local/bin/pip3
    RubyGems: 2.7.6 - /Users/XXX/.rvm/rubies/ruby-head/bin/gem
  Utilities:
    CMake: 3.16.4 - /usr/local/bin/cmake
    Make: 3.81 - /usr/bin/make
    GCC: 4.2.1 - /usr/bin/gcc
    Git: 2.32.0 - /usr/bin/git
    Clang: 13.0.0 - /usr/bin/clang
  Servers:
    Apache: 2.4.51 - /usr/sbin/apachectl
  Virtualization:
    Docker: 20.10.12 - /usr/local/bin/docker
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
  IDEs:
    Nano: 2.0.6 - /usr/bin/nano
    Vim: 8.2 - /usr/bin/vim
    WebStorm: 2021.3.1
    Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
  Languages:
    Bash: 3.2.57 - /bin/bash
    Perl: 5.30.3 - /usr/bin/perl
    Python: 2.7.18 - /usr/bin/python
    Python3: 3.9.7 - /usr/local/bin/python3
    Ruby: 2.6.0 - /Users/XXX/.rvm/rubies/ruby-head/bin/ruby
  Databases:
    MongoDB: 4.2.1 - /usr/local/bin/mongo
    PostgreSQL: 14.0 - /usr/local/bin/postgres
    SQLite: 3.36.0 - /usr/bin/sqlite3
  Browsers:
    Chrome: 97.0.4692.99
    Firefox: 57.0.4
    Safari: 15.2

Additional context (optional)

No response

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 24 (13 by maintainers)

Most upvoted comments

You shouldn’t be using localhost but 127.0.0.1 instead. Reason is that name resolution for localhost varies a lot between different systems and implementations of their network stacks.

Looks like Node v17+ changed to way localhost is being looked-up

Yes, partly. It just doesn’t reorder the DNS results anymore. That’s what we said all the time. The lookup works the same as before. Don’t use the DNS flag as it will prevent IPv6-connectivity. Just instead of localhost use 127.0.0.1.

for me, node 17 doesn’t work because somehow the example code simply doesn’t create the proxy from the right base url, it keeps using / to proxy for some reason. Using express, node 17, and used the example code provided.

The result is simply proxy didn’t work. I guess I have to use another library, was expecting this work out of box but somehow it just doesn’t work no matter what I do.

@chimurai Is it worth updating README.md (and examples) to use 127.0.0.1 instead of localhost? And/or mention that one should probably proxy to 127.0.0.1 instead of localhost etc? I’m thinking there are lots of people using this module during development, proxying to their API local server at localhost:1234. Could save some time for people, and avoid unnecessary issues being opened. 🤷‍♂️

Tricky stuff, it’s all about whether the server I proxy to accepts IPv4, IPv6 or both.

Here are some more details: https://github.com/nodejs/node/issues/40702#issuecomment-1103623246

@raspy8766 that’s a neat solution unfortunately for me, it won’t work since I have a case with multi-tenancy, and there’s a difference in dev between loading localhost to 127.0.0.1 to 0.0.0.0 (the URLs in my system apply the relevant tenant to the system and act with different results).

but probably for most cases - your solution is excellent.

I think I will close this bug since it’s actually a bug mostly in implementing dev environments with node, and not specifically for this middleware.

@chimurai the way we’re using http-proxy-middleware is through a node utility, so we can’t dictate what domain/ip-address they use specifically. In the meantime we have this workaround/hack in place for users on Node 17+:

  /**
   * Workaround for http-proxy-middleware DNS lookup issue with Nodejs 17+
   * [See here for details]{@link https://github.com/chimurai/http-proxy-middleware/issues/705#issuecomment-1126925635}
   **/
  target: target.replace('http://localhost', 'http://127.0.0.1'),

Any plans to fix this internally in the http-proxy-middleware library?

@krpeacock Yes, that’s why it was mentioned as a possibly breaking change and not introduced in 16, but in the short-term release 17, and also not backported to 16.

@davidmeirlevy Kind of. I haven’t figured out what’s the differenc when opening a listening socket and when opening a socket for connecting. However, even if querying localhost returns both IPv4 and IPv6, the host OS/libraries still have a say in ordering the results. E.g. if a host or even just a single interface doesn’t have IPv6 aside from the default link-local address, the system might decide that returning ::1 is not feasible and will still give precedence to 127.0.0.1.

You shouldn’t be using localhost but 127.0.0.1 instead. Reason is that name resolution for localhost varies a lot between different systems and implementations of their network stacks.

Thank you, this was the issue for me on Node 17 and 18, while the pattern was working on previous node versions