X Tutup
The Wayback Machine - https://web.archive.org/web/20201026035158/https://github.com/axios/axios/issues/2808
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More flexible ways to customize adapters #2808

Open
chinesedfan opened this issue Mar 7, 2020 · 10 comments
Open

More flexible ways to customize adapters #2808

chinesedfan opened this issue Mar 7, 2020 · 10 comments

Comments

@chinesedfan
Copy link
Collaborator

@chinesedfan chinesedfan commented Mar 7, 2020

Is your feature request related to a problem? Please describe.

Users may want to set different options for native http module, or do something with the request object. axios only supports some of them, but doesn't want to add more and more options. For example,

  • #974, to set req.setNoDelay for http adapter
  • #2233, to set options.localAddress
  • #2498, to set options.checkServerIdentity
  • #2930, to set options.insecureHTTPParser
  • #3138, to set options.dns

Describe the solution you'd like

Abstract the adapter as more detailed lifecycles, like beforeSend, afterSend. I just have the basic idea, but no detailed solution.

Describe alternatives you've considered

If only consider the options, we can add an extra config called adapterOptions. Otherwise, users must implement their own adapters.

Additional context

Should consider both xhr and http adapters to form a fixed pattern.

@rhorning
Copy link

@rhorning rhorning commented Mar 18, 2020

@chinesedfan, I don't really have a suggestion, but I also need #2233 (or an alternative to set the local address).

@seahindeniz
Copy link

@seahindeniz seahindeniz commented Mar 24, 2020

What about having something like beforeSend and transportOptions to avoid creating new and different options for each library?

Something like this usage:

/**
 * @param {import("http").ClientRequest | XMLHttpRequest} req 
 */
let beforeSend = (req) => {
  if (req instanceof XMLHttpRequest) {
    req.setRequestHeader("foo", "bar");
    req.onprogress = () => {
      // ... I know about axios has onUploadProgress but this is just an
      // example of how it can be used
    };
  } else {
    req.setNoDelay(true);
    req.setHeader("foo", "bar");
  }
};

/**
 * @type {import("http").RequestOptions}
 */
let transportOptions = {
  localAddress: "127.0.0.1",
};

let instance = axios.create({
  // ...
  beforeSend,
  transportOptions, // Node only
});

beforeSend will be called before these lines:

axios/lib/adapters/xhr.js

Lines 177 to 178 in 885ada6

// Send the request
request.send(requestData);

or this

axios/lib/adapters/http.js

Lines 275 to 282 in 885ada6

// Send the request
if (utils.isStream(data)) {
data.on('error', function handleStreamError(err) {
reject(enhanceError(err, config, null, req));
}).pipe(req);
} else {
req.end(data);
}

Since transportOptions can only be applied on Node side, it can be destructed in here

var options = {
path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
method: config.method.toUpperCase(),
headers: headers,
agent: agent,
agents: { http: config.httpAgent, https: config.httpsAgent },
auth: auth
};

Wdyt @chinesedfan?

@chinesedfan
Copy link
Collaborator Author

@chinesedfan chinesedfan commented Mar 26, 2020

@seahindeniz Yes, you shared most of idea with me. Maybe we can learn something from other libraries first, like got or request. It's not easy to design an ideal solution.

@Dramex
Copy link

@Dramex Dramex commented Apr 20, 2020

so right now we can't use localAddress with axios ? o.o

@github-actions
Copy link

@github-actions github-actions bot commented Jun 22, 2020

Hello! 👋 \n\nThis issue is being automatically marked as stale because it has not been updated in a while. Please confirm that the issue is still present and reproducible. If no updates or new comments are received the issue will be closed in a few days. \n\nThanks

@Poyoman39
Copy link

@Poyoman39 Poyoman39 commented Oct 6, 2020

As a workaround for options, waiting for #2808 to be implemented you may do something like :

  const wrappedHttp = {
    ...http,
    request: (options, callback) => http.request({
      ...options,
      localAddress: 'some.ip.add.ress',
    }, callback),
  };

  const instance = axios.create({
    transport: wrappedHttp,
  });
@carlchan1994
Copy link

@carlchan1994 carlchan1994 commented Oct 19, 2020

@Poyoman39 Poyoman39 I have tried your sample code to set up the localAddress but it does not work.
I have tried 'eth1' or private ip for the localAddress field.

@carlchan1994
Copy link

@carlchan1994 carlchan1994 commented Oct 19, 2020

@Poyoman39 Sorry I forgot this feature is not launched yet.

@Poyoman39
Copy link

@Poyoman39 Poyoman39 commented Oct 19, 2020

@carlchan1994 my sample should work with an IP. I tried it on a local server, and it seemed to work well. Be sure your outbound IP address is available => ip addr
Also be sure to use http or https based on what type of request you make

@carlchan1994
Copy link

@carlchan1994 carlchan1994 commented Oct 20, 2020

@Poyoman39 I tried again and success this time. Thanks a lot. Here is my code:

const axios = require('axios').default
const http = require('http')

function create_axios(ip){
  const wrappedHttp = {
    ...http,
    request: (options, callback) => http.request({
      ...options,
      localAddress: ip,
    }, callback),
  }

  return axios.create({
    transport: wrappedHttp,
  })
}

const eth0 = create_axios('10.180.60.82')
const eth1 = create_axios('10.180.60.83')
const eth2 = create_axios('10.180.60.84')
const eth3 = create_axios('10.180.60.85')

eth0.get('https://ifconfig.co/ip').then(res => { console.info(res.data) })
eth1.get('https://ifconfig.co/ip').then(res => { console.info(res.data) })
eth2.get('https://ifconfig.co/ip').then(res => { console.info(res.data) })
eth3.get('https://ifconfig.co/ip').then(res => { console.info(res.data) })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.
X Tutup