Closed zoli-kasa closed 1 year ago
We have noticed the same exact thing, working for axios version 0.27.2 but broken for version 1.1.2
Looking at the aws4-axios package.json, I see that this package is specifying "axios": ">=0.25.0"
as a peer dependency.
What if, for now this was changed to "axios": ">=0.25.0 < 1"
?
Then when axios fixes it's issue, this can be updated to >=1.0.0
or similar?
Same here. 👍
Still broken with axios 1.2.1.
npm is also partly to blame here as the resolutions in package.json should allow 0.2x to be installed but attempting to override it leads to invalid: "0.27.2" from node_modules ....
In addition to specifying "axios": ">=0.25.0 <1:"
in the overrides
field in package.json
, deleting node_modules
and package-lock.json
is required as per https://github.com/npm/cli/issues/4232
The axios team stated in multiple issues that they will not export helper functions in the foreseeable future. In my opinion, a path forward would be to replicate the used lib utility functions in the aws-axios codebase, as they are not overly complicated / difficult to maintain. @jamesmbourne What do you think? Would you be open to a pr?
We are facing the same issue too, works with 0.27.2
@jamesmbourne Could you have a look at my proposal https://github.com/jamesmbourne/aws4-axios/issues/701#issuecomment-1353024764 ? Would you be open to a PR?
@jamesmbourne Could you have a look at my proposal https://github.com/jamesmbourne/aws4-axios/issues/701#issuecomment-1353024764 ? Would you be open to a PR?
I'm tempted to fork this just to be able to address this issue.
@jamesmbourne Could you have a look at my proposal #701 (comment) ? Would you be open to a PR?
I'm tempted to fork this just to be able to address this issue.
that's great, go for it if you have time! the package looks kind of abandoned :(
Hi all, sorry I haven't had the time to put any effort into maintain this package over the past year.
I'm not currently using this package for any of my projects (I've switched to https://github.com/sindresorhus/got for most things).
That said, it's clear that this package is still depended upon by a lot of projects, so I'll try and at least get it to a state where it's compatible with axios>=1.0.0
.
If anyone has forked the project to add support for this, I'd be very welcoming of PRs and will endeavour to get those merged and released ASAP.
I've taken a look at this and currently I think we would need to include half of Axios's helpers
dir in this repo. The most complex function used is https://github.com/axios/axios/blob/v1.x/lib/helpers/buildURL.js due to a number of other dependencies.
If I went ahead and copied these implementations into this repo, there is a high likelihood of something breaking due to subtle differences in how the "copy" of Axios in this repo behaves compared with the real version.
Please could you give a 👍 on this issue: https://github.com/axios/axios/issues/4793
Having the final request URL available in interceptors seems like the only sensible way to go about achieving compatibility with Axios 1.x to me.
@jamesmbourne Is it only about the final url? If so, this should work:
const client = axios.create({
baseURL: "https://some-domain.com/api/",
params: { foo: "bar" },
});
client.interceptors.request.use(async (config) => {
console.log("config", config);
const uri = client.getUri(config);
console.log("final uri", uri); // final uri https://some-domain.com/api/foooooo?foo=bar
return config;
});
try {
const a = await client.get("/foooooo");
} catch (error) {
console.log(error);
}
Just a quick demo:
import { fromIni } from "@aws-sdk/credential-providers";
import aws4 from "aws4";
import axios from "axios"; // current axios version
import type { AwsCredentialIdentity, Provider } from "@aws-sdk/types";
import type {
AxiosInstance,
AxiosRequestConfig,
AxiosRequestHeaders,
InternalAxiosRequestConfig,
Method,
} from "axios";
const getTransformer = (config: AxiosRequestConfig) => {
const { transformRequest } = config;
if (transformRequest) {
if (typeof transformRequest === "function") {
return transformRequest;
} else if (transformRequest.length) {
return transformRequest[0];
}
}
throw new Error("Could not get default transformRequest function from Axios defaults");
};
const client = axios.create({
baseURL: "https://some-url.com",
});
export const aws4Interceptor =
({
instance = axios,
credentials,
options,
}: {
instance: AxiosInstance;
options?: InterceptorOptions;
credentials: AwsCredentialIdentity | Provider<AwsCredentialIdentity>;
}): ((config: InternalAxiosRequestConfig) => Promise<InternalAxiosRequestConfig>) =>
async (config): Promise<InternalAxiosRequestConfig> => {
const url = instance.getUri(config);
console.log("final url", url);
const { host, pathname, search } = new URL(url);
const { data, headers, method } = config;
const transformRequest = getTransformer(config);
// @ts-ignore
const transformedData = transformRequest(data, headers);
// Remove all the default Axios headers
const {
common,
delete: _delete, // 'delete' is a reserved word
get,
head,
post,
put,
patch,
...headersToSign
} = headers as any as InternalAxiosHeaders;
// Axios type definitions do not match the real shape of this object
const signingOptions: SigningOptions = {
method: method && method.toUpperCase(),
host,
path: pathname + search,
region: options?.region,
service: options?.service,
signQuery: options?.signQuery,
body: transformedData,
headers: headersToSign as any,
};
const resolvedCredentials =
typeof credentials === "function"
? await credentials()
: credentials ?? {
accessKeyId: "",
secretAccessKey: "",
};
// using aws4
aws4.sign(signingOptions as any, resolvedCredentials); // TODO typing
config.headers = signingOptions.headers as any; // TODO typing
if (signingOptions.signQuery) {
const originalUrl = new URL(url);
const signedUrl = new URL(originalUrl.origin + signingOptions.path);
config.url = signedUrl.toString();
}
return config;
};
const interceptor = aws4Interceptor({
instance: client,
credentials: fromIni({ profile: "some-profile" }),
options: {
region: "eu-central-1",
service: "execute-api",
},
});
client.interceptors.request.use(interceptor);
try {
const a = await client.get("/games", { params: { foo: "bar" } });
console.log("request succeed");
} catch (error) {
console.log("req failed", error);
}
export type InternalAxiosHeaders = Record<Method | "common", Record<string, string>>;
export interface SigningOptions {
host?: string;
headers?: AxiosRequestHeaders;
path?: string;
body?: unknown;
region?: string;
service?: string;
signQuery?: boolean;
method?: string;
}
export interface Credentials {
accessKeyId: string;
secretAccessKey: string;
sessionToken?: string;
}
export type InterceptorOptions = {
/**
* Target service. Will use default aws4 behavior if not given.
*/
service?: string;
/**
* AWS region name. Will use default aws4 behavior if not given.
*/
region?: string;
/**
* Whether to sign query instead of adding Authorization header. Default to false.
*/
signQuery?: boolean;
/**
* ARN of the IAM Role to be assumed to get the credentials from.
* The credentials will be cached and automatically refreshed as needed.
* Will not be used if credentials are provided.
*/
assumeRoleArn?: string;
/**
* Number of seconds before the assumed Role expiration
* to invalidate the cache.
* Used only if assumeRoleArn is provided.
*/
assumedRoleExpirationMarginSec?: number;
};
@jamesmbourne the axios internals are now exposed again: https://github.com/axios/axios/pull/5677, released as of 1.4.0.
Great news, thanks for sharing @tusbar! I’ll take a look at getting a PR ready using the newly exposed helpers.
@jamesmbourne As shown above, it might not be necessary to rely on the internal helpers. Axios maintainers marked them as unsafe and announced that they plan to refactor them. I am using the PoC above https://github.com/jamesmbourne/aws4-axios/issues/701#issuecomment-1484136280 for signing requests to an apigw and it works fine.
@jamesmbourne As shown above, it might not be necessary to rely on the internal helpers. Axios maintainers marked them as unsafe and announced that they plan to refactor them. I am using the PoC above #701 (comment) for signing requests to an apigw and it works fine.
@florianbepunkt aren't you planning to release that as a standalone NPM package?
@zoli-kasa Haven't thought about it. I prefer contributing to existing solutions. Publishing another package would add to (unnecessarily) fragmenting the solution space. I'm not against using the internal helpers and I have used this library extensively in the past. I just wondered whether the task at hand can be accomplished with the public API, which might make maintenance of this lib easier in the future.
Thanks for the suggestions all, especially @florianbepunkt!
client.getUri
works nicely. I've pushed to https://github.com/jamesmbourne/aws4-axios/pull/835 and all the tests were passing.
I just need to update the docs and then we should be able to get a new v3 release out.
:tada: This issue has been resolved in version 3.0.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
We just upgraded to Axios 1.6.0 and found that aws4-axios is not compatible. Could you please look into it? Thanks!
using the example
with latest axios (1.1.2) i get the following error
with axios 0.27, it works fine.