Skip to content

JS: ClientRequests Axios Instance support #19655

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added support for Axios instances in the `axios` module.
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ module ClientRequest {
method = "request" and
result = this.getOptionArgument(0, "data")
or
method = ["post", "put"] and
method = ["post", "put", "patch"] and
result = [this.getArgument(1), this.getOptionArgument(2, "data")]
or
method = ["postForm", "putForm", "patchForm"] and result = this.getArgument(1)
Expand Down Expand Up @@ -289,6 +289,69 @@ module ClientRequest {
}
}

/**
* A model of a `axios` instance request.
*/
class AxiosInstanceRequest extends ClientRequest::Range, API::CallNode {
string method;
API::CallNode instance;

// Instances of axios, e.g. `axios.create({ ... })`
AxiosInstanceRequest() {
instance = axios().getMember(["create", "createInstance"]).getACall() and
method = [httpMethodName(), "request", "postForm", "putForm", "patchForm", "getUri"] and
this = instance.getReturn().getMember(method).getACall()
}

private int getOptionsArgIndex() {
(method = "get" or method = "delete" or method = "head") and
result = 0
or
(method = "post" or method = "put" or method = "patch") and
result = 1
}

private DataFlow::Node getOptionArgument(string name) {
result = this.getOptionArgument(this.getOptionsArgIndex(), name)
}

override DataFlow::Node getUrl() {
result = this.getArgument(0) or
result = this.getOptionArgument(urlPropertyName())
}

override DataFlow::Node getHost() { result = instance.getOptionArgument(0, "baseURL") }

override DataFlow::Node getADataNode() {
method = ["post", "put", "patch"] and
result = [this.getArgument(1), this.getOptionArgument(2, "data")]
or
method = ["postForm", "putForm", "patchForm"] and result = this.getArgument(1)
or
result = this.getOptionArgument([0 .. 2], ["headers", "params"])
}

/** Gets the response type from the options passed in. */
string getResponseType() {
exists(DataFlow::Node option | option = instance.getOptionArgument(0, "responseType") |
option.mayHaveStringValue(result)
)
or
not exists(this.getOptionArgument("responseType")) and
result = "json"
}

override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
responseType = this.getResponseType() and
promise = true and
result = this
or
responseType = this.getResponseType() and
promise = false and
result = this.getReturn().getPromisedError().getMember("response").asSource()
}
}

/** An expression that is used as a credential in a request. */
private class AuthorizationHeader extends CredentialsNode {
AuthorizationHeader() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ test_ClientRequest
| apollo.js:17:1:17:34 | new Pre ... yurl"}) |
| apollo.js:20:1:20:77 | createN ... phql'}) |
| apollo.js:23:1:23:31 | new Web ... wsUri}) |
| axios.ts:14:32:14:65 | api.get ... repo}`) |
| axios.ts:25:32:25:73 | api.pat ... , data) |
| axiosTest.js:4:5:7:6 | axios({ ... \\n }) |
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) |
| puppeteer.ts:6:11:6:42 | page.go ... e.com') |
Expand Down Expand Up @@ -111,6 +113,7 @@ test_ClientRequest
| tst.js:349:5:349:30 | axios.g ... url }) |
| tst.js:352:5:352:66 | axiosIn ... text"}) |
test_getADataNode
| axios.ts:25:32:25:73 | api.pat ... , data) | axios.ts:25:69:25:72 | data |
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:15:18:15:55 | { 'Cont ... json' } |
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:16:15:16:35 | {x: 'te ... 'test'} |
| superagent.js:6:5:6:32 | superag ... st(url) | superagent.js:6:39:6:42 | data |
Expand Down Expand Up @@ -159,6 +162,8 @@ test_getADataNode
| tst.js:347:5:347:30 | axios.p ... , data) | tst.js:347:26:347:29 | data |
| tst.js:348:5:348:38 | axios.p ... config) | tst.js:348:26:348:29 | data |
test_getHost
| axios.ts:14:32:14:65 | api.get ... repo}`) | axios.ts:4:14:4:37 | "https: ... ub.com" |
| axios.ts:25:32:25:73 | api.pat ... , data) | axios.ts:4:14:4:37 | "https: ... ub.com" |
| tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host |
| tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host |
| tst.js:91:5:91:34 | got(rel ... host}) | tst.js:91:29:91:32 | host |
Expand All @@ -173,6 +178,8 @@ test_getUrl
| apollo.js:17:1:17:34 | new Pre ... yurl"}) | apollo.js:17:26:17:32 | "myurl" |
| apollo.js:20:1:20:77 | createN ... phql'}) | apollo.js:20:30:20:75 | 'https: ... raphql' |
| apollo.js:23:1:23:31 | new Web ... wsUri}) | apollo.js:23:25:23:29 | wsUri |
| axios.ts:14:32:14:65 | api.get ... repo}`) | axios.ts:14:40:14:64 | `/repos ... {repo}` |
| axios.ts:25:32:25:73 | api.pat ... , data) | axios.ts:25:42:25:66 | `/repos ... {repo}` |
| axiosTest.js:4:5:7:6 | axios({ ... \\n }) | axiosTest.js:4:11:7:5 | {\\n ... ,\\n } |
| axiosTest.js:4:5:7:6 | axios({ ... \\n }) | axiosTest.js:6:14:6:16 | url |
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:12:11:17:5 | {\\n ... }\\n } |
Expand Down Expand Up @@ -289,6 +296,8 @@ test_getUrl
| tst.js:352:5:352:66 | axiosIn ... text"}) | tst.js:352:19:352:65 | {method ... "text"} |
| tst.js:352:5:352:66 | axiosIn ... text"}) | tst.js:352:40:352:42 | url |
test_getAResponseDataNode
| axios.ts:14:32:14:65 | api.get ... repo}`) | axios.ts:14:32:14:65 | api.get ... repo}`) | json | true |
| axios.ts:25:32:25:73 | api.pat ... , data) | axios.ts:25:32:25:73 | api.pat ... , data) | json | true |
| axiosTest.js:4:5:7:6 | axios({ ... \\n }) | axiosTest.js:4:5:7:6 | axios({ ... \\n }) | json | true |
| axiosTest.js:12:5:17:6 | axios({ ... \\n }) | axiosTest.js:12:5:17:6 | axios({ ... \\n }) | json | true |
| superagent.js:4:5:4:26 | superag ... ', url) | superagent.js:4:5:4:26 | superag ... ', url) | stream | true |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import axios from "axios";

let api = axios.create({
baseURL: "https://api.github.com",
timeout: 1000,
responseType: "json",
headers: { "X-Custom-Header": "foobar" }
});

export default api;

export async function getRepo(owner: string, repo: string) {
try {
const response = await api.get(`/repos/${owner}/${repo}`);
console.log("Repository data:", response.data);
return response.data;
} catch (error) {
console.error("Error fetching repo:", error);
throw error;
}
}

export async function updateUser(owner: string, repo: string, data: any) {
try {
const response = await api.patch(`/repos/${owner}/${repo}`, data);
console.log("User updated:", response.data);
return response.data;
} catch (error) {
console.error("Error updating user:", error);
throw error;
}
}