Skip to content

Commit

Permalink
Add support for multi form parameter support (#1836)
Browse files Browse the repository at this point in the history
* add support for multi query params

* handle edge case

* cleanup

* docs

* Regenerate client from commit aeb956c4 of spec repo

---------

Co-authored-by: Sherzod Karimov <[email protected]>
Co-authored-by: api-clients-generation-pipeline[bot] <54105614+api-clients-generation-pipeline[bot]@users.noreply.github.com>
Co-authored-by: ci.datadog-api-spec <[email protected]>
  • Loading branch information
3 people authored Nov 4, 2024
1 parent ac0f7f2 commit e600a8f
Show file tree
Hide file tree
Showing 59 changed files with 1,138 additions and 516 deletions.
8 changes: 4 additions & 4 deletions .apigentools-info
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"spec_versions": {
"v1": {
"apigentools_version": "1.6.6",
"regenerated": "2024-11-04 17:58:11.008472",
"spec_repo_commit": "6ffe013b"
"regenerated": "2024-11-04 18:34:30.221886",
"spec_repo_commit": "aeb956c4"
},
"v2": {
"apigentools_version": "1.6.6",
"regenerated": "2024-11-04 17:58:11.026745",
"spec_repo_commit": "6ffe013b"
"regenerated": "2024-11-04 18:34:30.241262",
"spec_repo_commit": "aeb956c4"
}
}
}
2 changes: 2 additions & 0 deletions .generator/src/generator/openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ def collection_format(parameter):
explode = parameter.get("explode", True if style == "form" else False)
return matrix.get((style, explode), "multi")

return ""


def format_server(server, server_variables=None, path=""):
url = server["url"] + path
Expand Down
2 changes: 1 addition & 1 deletion .generator/src/generator/templates/api/api.j2
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class {{ className }}RequestFactory extends BaseAPIRequestFactory {
// Query Params
{%- endif %}
if ({{ name|attribute_name }} !== undefined) {
requestContext.setQueryParam("{{ name }}", ObjectSerializer.serialize({{ name|attribute_name }}, "{{ get_type_for_parameter(parameter) }}", "{{ get_format_for_schema(parameter) }}"));
requestContext.setQueryParam("{{ name }}", ObjectSerializer.serialize({{ name|attribute_name }}, "{{ get_type_for_parameter(parameter) }}", "{{ get_format_for_schema(parameter) }}"), "{{ parameter|collection_format }}");
}
{%- endfor %}

Expand Down
33 changes: 25 additions & 8 deletions .generator/src/generator/templates/http/http.j2
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { userAgent } from "../../../userAgent";
// TODO: evaluate if we can easily get rid of this library
import FormData from "form-data";
import URLParse from "url-parse";
import { isBrowser } from "../util";
import { COLLECTION_FORMATS } from "../baseapi";

/**
* Interface for aborting fetch requests.
Expand Down Expand Up @@ -88,7 +88,7 @@ export interface HttpConfiguration {
export class RequestContext {
private headers: { [key: string]: string } = {};
private body: RequestBody = undefined;
private url: URLParse;
private url: URL;
private httpConfig: HttpConfiguration = {};

/**
Expand All @@ -98,7 +98,7 @@ export class RequestContext {
* @param httpMethod http method
*/
public constructor(url: string, private httpMethod: HttpMethod) {
this.url = new URLParse(url, true);
this.url = new URL(url);
if (!isBrowser) {
this.headers = { "user-agent": userAgent };
}
Expand All @@ -117,7 +117,7 @@ export class RequestContext {
*
*/
public setUrl(url: string): void {
this.url = new URLParse(url, true);
this.url = new URL(url);
}

/**
Expand Down Expand Up @@ -145,10 +145,27 @@ export class RequestContext {
return this.body;
}

public setQueryParam(name: string, value: string): void {
const queryObj = this.url.query;
queryObj[name] = value;
this.url.set("query", queryObj);
/**
* Sets query parameters on the request URL
*
* @param name the name of the query parameter
* @param value the value of the query parameter
* @param collectionFormat the format of the query parameter See https://spec.openapis.org/oas/v3.0.2#style-values
*/
public setQueryParam(name: string, value: string | string[], collectionFormat: string): void {
if (collectionFormat === "multi") {
for (const val of value) {
this.url.searchParams.append(name, val);
}
return;
}

if (Array.isArray(value)) {
const delimiter = COLLECTION_FORMATS[collectionFormat as keyof typeof COLLECTION_FORMATS];
value = value.join(delimiter);
}

return this.url.searchParams.set(name, value);
}

/**
Expand Down
2 changes: 0 additions & 2 deletions LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Component,Licence,Copyright
@types/jest,MIT,Copyright Microsoft Corporation
@types/node,MIT,Copyright Microsoft Corporation
@types/pako,MIT,Copyright Caleb Eggensperger Muhammet Öztürk
@types/url-parse,MIT,Copyright Microsoft Corporation
@typescript-eslint/eslint-plugin,MIT,Copyright (c) 2019 TypeScript ESLint and other contributors
@typescript-eslint/parser,BSD-2-Clause,
buffer-from,MIT,Copyright (c) 2016, 2018 Linus Unnebäck
Expand All @@ -31,6 +30,5 @@ prettier,MIT,Copyright © James Long and contributors
ts-node,MIT,Copyright (c) 2014 Blake Embrey ([email protected])
typedoc,Apache-2.0,Copyright (c) 2015 Sebastian Lenz Copyright (c) 2016-2021 TypeDoc Contributors.
typescript,Apache-2.0,Copyright (c) Microsoft Corporation.
url-parse,MIT,Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors.
loglevel,MIT,Copyright (c) 2013 Tim Perry
zstd.ts,BSD-2-Clause,Copyright (c) [2021] [Beeno Tung (Tung Cheung Leong)]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"2024-10-21T20:05:58.636Z"
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"log": {
"_recordingName": "Security Monitoring/List findings with detection_type query param returns \"OK\" response",
"creator": {
"comment": "persister:fs",
"name": "Polly.JS",
"version": "6.0.5"
},
"entries": [
{
"_id": "5f6fcc703704b0462fc33728fd9b12b2",
"_order": 0,
"cache": {},
"request": {
"bodySize": 0,
"cookies": [],
"headers": [
{
"_fromType": "array",
"name": "accept",
"value": "application/json"
}
],
"headersSize": 611,
"httpVersion": "HTTP/1.1",
"method": "GET",
"queryString": [
{
"name": "filter",
"value": {
"vulnerability_type": [
"misconfiguration",
"attack_path"
]
}
}
],
"url": "https://api.datadoghq.com/api/v2/posture_management/findings?filter%5Bvulnerability_type%5D=misconfiguration&filter%5Bvulnerability_type%5D=attack_path"
},
"response": {
"bodySize": 89,
"content": {
"mimeType": "application/vnd.api+json",
"size": 89,
"text": "{\"data\":[],\"meta\":{\"page\":{\"total_filtered_count\":0},\"snapshot_timestamp\":1729541158755}}"
},
"cookies": [],
"headers": [
{
"name": "content-type",
"value": "application/vnd.api+json"
}
],
"headersSize": 524,
"httpVersion": "HTTP/1.1",
"redirectURL": "",
"status": 200,
"statusText": "OK"
},
"startedDateTime": "2024-10-21T20:05:58.644Z",
"time": 141
}
],
"pages": [],
"version": "1.2"
}
}
22 changes: 22 additions & 0 deletions examples/v2/security-monitoring/ListFindings_1668290866.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* List findings with detection_type query param returns "OK" response
*/

import { client, v2 } from "@datadog/datadog-api-client";

const configuration = client.createConfiguration();
configuration.unstableOperations["v2.listFindings"] = true;
const apiInstance = new v2.SecurityMonitoringApi(configuration);

const params: v2.SecurityMonitoringApiListFindingsRequest = {
filterVulnerabilityType: ["misconfiguration", "attack_path"],
};

apiInstance
.listFindings(params)
.then((data: v2.ListFindingsResponse) => {
console.log(
"API called successfully. Returned data: " + JSON.stringify(data)
);
})
.catch((error: any) => console.error(error));
8 changes: 8 additions & 0 deletions features/v2/security_monitoring.feature
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,14 @@ Feature: Security Monitoring
When the request with pagination is sent
Then the response status is 200 OK

@skip-terraform-config @team:DataDog/cloud-security-posture-management
Scenario: List findings with detection_type query param returns "OK" response
Given operation "ListFindings" enabled
And new "ListFindings" request
And request contains "filter[vulnerability_type]" parameter with value ["misconfiguration", "attack_path"]
When the request is sent
Then the response status is 200 OK

@generated @skip @team:DataDog/k9-cloud-security-platform
Scenario: List rules returns "Bad Request" response
Given new "ListSecurityMonitoringRules" request
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@
"es6-promise": "^4.2.8",
"form-data": "^4.0.0",
"loglevel": "^1.8.1",
"pako": "^2.0.4",
"url-parse": "^1.4.3"
"pako": "^2.0.4"
},
"resolutions": {
"@pollyjs/adapter-node-http/nock": "^13.1.3"
Expand All @@ -86,7 +85,6 @@
"@pollyjs/persister-fs": "^6.0.5",
"@types/chai": "^4.3.4",
"@types/jest": "^29.5.2",
"@types/url-parse": "^1.4.3",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"chai": "^4.3.7",
Expand Down
38 changes: 30 additions & 8 deletions packages/datadog-api-client-common/http/http.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { userAgent } from "../../../userAgent";
// TODO: evaluate if we can easily get rid of this library
import FormData from "form-data";
import URLParse from "url-parse";
import { isBrowser } from "../util";
import { COLLECTION_FORMATS } from "../baseapi";

/**
* Interface for aborting fetch requests.
Expand Down Expand Up @@ -88,7 +88,7 @@ export interface HttpConfiguration {
export class RequestContext {
private headers: { [key: string]: string } = {};
private body: RequestBody = undefined;
private url: URLParse;
private url: URL;
private httpConfig: HttpConfiguration = {};

/**
Expand All @@ -101,7 +101,7 @@ export class RequestContext {
url: string,
private httpMethod: HttpMethod
) {
this.url = new URLParse(url, true);
this.url = new URL(url);
if (!isBrowser) {
this.headers = { "user-agent": userAgent };
}
Expand All @@ -120,7 +120,7 @@ export class RequestContext {
*
*/
public setUrl(url: string): void {
this.url = new URLParse(url, true);
this.url = new URL(url);
}

/**
Expand Down Expand Up @@ -148,10 +148,32 @@ export class RequestContext {
return this.body;
}

public setQueryParam(name: string, value: string): void {
const queryObj = this.url.query;
queryObj[name] = value;
this.url.set("query", queryObj);
/**
* Sets query parameters on the request URL
*
* @param name the name of the query parameter
* @param value the value of the query parameter
* @param collectionFormat the format of the query parameter See https://spec.openapis.org/oas/v3.0.2#style-values
*/
public setQueryParam(
name: string,
value: string | string[],
collectionFormat: string
): void {
if (collectionFormat === "multi") {
for (const val of value) {
this.url.searchParams.append(name, val);
}
return;
}

if (Array.isArray(value)) {
const delimiter =
COLLECTION_FORMATS[collectionFormat as keyof typeof COLLECTION_FORMATS];
value = value.join(delimiter);
}

return this.url.searchParams.set(name, value);
}

/**
Expand Down
21 changes: 14 additions & 7 deletions packages/datadog-api-client-v1/apis/AWSIntegrationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,19 +364,22 @@ export class AWSIntegrationApiRequestFactory extends BaseAPIRequestFactory {
if (accountId !== undefined) {
requestContext.setQueryParam(
"account_id",
ObjectSerializer.serialize(accountId, "string", "")
ObjectSerializer.serialize(accountId, "string", ""),
""
);
}
if (roleName !== undefined) {
requestContext.setQueryParam(
"role_name",
ObjectSerializer.serialize(roleName, "string", "")
ObjectSerializer.serialize(roleName, "string", ""),
""
);
}
if (accessKeyId !== undefined) {
requestContext.setQueryParam(
"access_key_id",
ObjectSerializer.serialize(accessKeyId, "string", "")
ObjectSerializer.serialize(accessKeyId, "string", ""),
""
);
}

Expand Down Expand Up @@ -438,7 +441,8 @@ export class AWSIntegrationApiRequestFactory extends BaseAPIRequestFactory {
if (accountId !== undefined) {
requestContext.setQueryParam(
"account_id",
ObjectSerializer.serialize(accountId, "string", "")
ObjectSerializer.serialize(accountId, "string", ""),
""
);
}

Expand Down Expand Up @@ -479,19 +483,22 @@ export class AWSIntegrationApiRequestFactory extends BaseAPIRequestFactory {
if (accountId !== undefined) {
requestContext.setQueryParam(
"account_id",
ObjectSerializer.serialize(accountId, "string", "")
ObjectSerializer.serialize(accountId, "string", ""),
""
);
}
if (roleName !== undefined) {
requestContext.setQueryParam(
"role_name",
ObjectSerializer.serialize(roleName, "string", "")
ObjectSerializer.serialize(roleName, "string", ""),
""
);
}
if (accessKeyId !== undefined) {
requestContext.setQueryParam(
"access_key_id",
ObjectSerializer.serialize(accessKeyId, "string", "")
ObjectSerializer.serialize(accessKeyId, "string", ""),
""
);
}

Expand Down
Loading

0 comments on commit e600a8f

Please sign in to comment.