diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1392be5f2d..6d87a4f3dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Better client configuration #268
- Request builders constructors for data validation #322
+- Adds middleware support for http clients #330
## [0.0.5] - 2021-06-10
diff --git a/abstractions/dotnet/src/IMiddlewareOption.cs b/abstractions/dotnet/src/IMiddlewareOption.cs
new file mode 100644
index 0000000000..2d416c9f47
--- /dev/null
+++ b/abstractions/dotnet/src/IMiddlewareOption.cs
@@ -0,0 +1,7 @@
+namespace Microsoft.Kiota.Abstractions {
+ ///
+ /// Represents a middleware option.
+ ///
+ public interface IMiddlewareOption {
+ }
+}
diff --git a/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj b/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
index 19f0dbe9f9..c8689b793a 100644
--- a/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
+++ b/abstractions/dotnet/src/Microsoft.Kiota.Abstractions.csproj
@@ -4,7 +4,7 @@
net5.0
true
https://github.com/microsoft/kiota
- 1.0.13
+ 1.0.14
diff --git a/abstractions/dotnet/src/RequestInfo.cs b/abstractions/dotnet/src/RequestInfo.cs
index 42c20d2665..e26c814b51 100644
--- a/abstractions/dotnet/src/RequestInfo.cs
+++ b/abstractions/dotnet/src/RequestInfo.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Collections.Generic;
using System.IO;
using Microsoft.Kiota.Abstractions.Serialization;
@@ -30,6 +31,30 @@ public class RequestInfo
/// The Request Body.
///
public Stream Content { get; set; }
+ private Dictionary _middlewareOptions = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ ///
+ /// Gets the middleware options for this request. Options are unique by type. If an option of the same type is added twice, the last one wins.
+ ///
+ public IEnumerable MiddlewareOptions { get { return _middlewareOptions.Values; } }
+ ///
+ /// Adds a middleware option to the request.
+ ///
+ /// The middleware option to add.
+ public void AddMiddlewareOptions(params IMiddlewareOption[] options) {
+ if(!options?.Any() ?? false) return; // it's a no-op if there are no options and this avoid having to check in the code gen.
+ foreach(var option in options.Where(x => x != null))
+ if(!_middlewareOptions.TryAdd(option.GetType().FullName, option))
+ _middlewareOptions[option.GetType().FullName] = option;
+ }
+ ///
+ /// Removes given middleware options from the current request.
+ ///
+ /// Middleware options to remove.
+ public void RemoveMiddlewareOptions(params IMiddlewareOption[] options) {
+ if(!options?.Any() ?? false) throw new ArgumentNullException(nameof(options));
+ foreach(var optionName in options.Where(x => x != null).Select(x => x.GetType().FullName))
+ _middlewareOptions.Remove(optionName);
+ }
private const string binaryContentType = "application/octet-stream";
private const string contentTypeHeader = "Content-Type";
///
diff --git a/abstractions/java/lib/build.gradle b/abstractions/java/lib/build.gradle
index e2a39ac1d0..efff7f9aa9 100644
--- a/abstractions/java/lib/build.gradle
+++ b/abstractions/java/lib/build.gradle
@@ -46,7 +46,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-abstractions'
- version '1.0.13'
+ version '1.0.14'
from(components.java)
}
}
diff --git a/abstractions/java/lib/src/main/java/com/microsoft/kiota/MiddlewareOption.java b/abstractions/java/lib/src/main/java/com/microsoft/kiota/MiddlewareOption.java
new file mode 100644
index 0000000000..bffcaaaf49
--- /dev/null
+++ b/abstractions/java/lib/src/main/java/com/microsoft/kiota/MiddlewareOption.java
@@ -0,0 +1,6 @@
+package com.microsoft.kiota;
+
+/** Represents a middleware option. */
+public interface MiddlewareOption {
+
+}
\ No newline at end of file
diff --git a/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java b/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
index 335ceefa38..5498b5f12a 100644
--- a/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
+++ b/abstractions/java/lib/src/main/java/com/microsoft/kiota/RequestInfo.java
@@ -3,6 +3,7 @@
import java.net.URI;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;
import java.util.function.Function;
@@ -31,6 +32,32 @@ public class RequestInfo {
/** The Request Body. */
@Nullable
public InputStream content;
+ private HashMap _middlewareOptions = new HashMap<>();
+ /**
+ * Gets the middleware options for this request. Options are unique by type. If an option of the same type is added twice, the last one wins.
+ * @return the middleware options for this request.
+ */
+ public Collection getMiddlewareOptions() { return _middlewareOptions.values(); }
+ /**
+ * Adds a middleware option to this request.
+ * @param option the middleware option to add.
+ */
+ public void addMiddlewareOptions(@Nullable final MiddlewareOption... options) {
+ if(options == null || options.length == 0) return;
+ for(final MiddlewareOption option : options) {
+ _middlewareOptions.put(option.getClass().getCanonicalName(), option);
+ }
+ }
+ /**
+ * Removes a middleware option from this request.
+ * @param option the middleware option to remove.
+ */
+ public void removeMiddlewareOptions(@Nullable final MiddlewareOption... options) {
+ if(options == null || options.length == 0) return;
+ for(final MiddlewareOption option : options) {
+ _middlewareOptions.remove(option.getClass().getCanonicalName());
+ }
+ }
private static String binaryContentType = "application/octet-stream";
private static String contentTypeHeader = "Content-Type";
/**
diff --git a/abstractions/typescript/package-lock.json b/abstractions/typescript/package-lock.json
index 848f2f4272..58e42ba014 100644
--- a/abstractions/typescript/package-lock.json
+++ b/abstractions/typescript/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-abstractions",
- "version": "1.0.13",
+ "version": "1.0.14",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/abstractions/typescript/package.json b/abstractions/typescript/package.json
index 1b3e30c81b..139040ac53 100644
--- a/abstractions/typescript/package.json
+++ b/abstractions/typescript/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-abstractions",
- "version": "1.0.13",
+ "version": "1.0.14",
"description": "Core abstractions for kiota generated libraries in TypeScript and JavaScript",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/abstractions/typescript/src/index.ts b/abstractions/typescript/src/index.ts
index cd6b5b6955..627037850c 100644
--- a/abstractions/typescript/src/index.ts
+++ b/abstractions/typescript/src/index.ts
@@ -8,4 +8,5 @@ export * from "./nativeResponseHandler";
export * from "./nativeResponseWrapper";
export * from './serialization';
export * from './utils';
-export * from './store';
\ No newline at end of file
+export * from './store';
+export * from './middlewareOption';
\ No newline at end of file
diff --git a/abstractions/typescript/src/middlewareOption.ts b/abstractions/typescript/src/middlewareOption.ts
new file mode 100644
index 0000000000..fa1a47ee1d
--- /dev/null
+++ b/abstractions/typescript/src/middlewareOption.ts
@@ -0,0 +1,5 @@
+/** Represents a middleware option. */
+export interface MiddlewareOption {
+ /** Gets the option key for when adding it to a request. Must be unique. */
+ getKey(): string;
+}
\ No newline at end of file
diff --git a/abstractions/typescript/src/requestInfo.ts b/abstractions/typescript/src/requestInfo.ts
index 1846ed074b..5973f39961 100644
--- a/abstractions/typescript/src/requestInfo.ts
+++ b/abstractions/typescript/src/requestInfo.ts
@@ -2,6 +2,7 @@ import { HttpMethod } from "./httpMethod";
import { ReadableStream } from 'web-streams-polyfill/es2018';
import { Parsable } from "./serialization";
import { HttpCore } from "./httpCore";
+import { MiddlewareOption } from "./middlewareOption";
/** This class represents an abstract HTTP request. */
export class RequestInfo {
@@ -15,6 +16,22 @@ export class RequestInfo {
public queryParameters: Map = new Map(); //TODO: case insensitive
/** The Request Headers. */
public headers: Map = new Map(); //TODO: case insensitive
+ private _middlewareOptions = new Map(); //TODO: case insensitive
+ /** Gets the middleware options for the request. */
+ public getMiddlewareOptions() { return this._middlewareOptions.values(); }
+ public addMiddlewareOptions(...options: MiddlewareOption[]) {
+ if(!options || options.length === 0) return;
+ options.forEach(option => {
+ this._middlewareOptions.set(option.getKey(), option);
+ });
+ }
+ /** Removes the middleware options for the request. */
+ public removeMiddlewareOptions(...options: MiddlewareOption[]) {
+ if(!options || options.length === 0) return;
+ options.forEach(option => {
+ this._middlewareOptions.delete(option.getKey());
+ });
+ }
private static binaryContentType = "application/octet-stream";
private static contentTypeHeader = "Content-Type";
/**
diff --git a/http/dotnet/httpclient/src/HttpClientBuilder.cs b/http/dotnet/httpclient/src/HttpClientBuilder.cs
new file mode 100644
index 0000000000..ee2f0426b6
--- /dev/null
+++ b/http/dotnet/httpclient/src/HttpClientBuilder.cs
@@ -0,0 +1,49 @@
+using System.Linq;
+using System.Collections.Generic;
+using System.Net.Http;
+using Microsoft.Kiota.Abstractions;
+
+namespace Microsoft.Kiota.Http.HttpClient {
+ ///
+ /// This class is used to build the HttpClient instance used by the core service.
+ ///
+ public static class HttpClientBuilder {
+ ///
+ /// Initializes the with the default configuration and middlewares including a authentention middleware using the if provided.
+ ///
+ /// The to use for authentention.
+ /// The with the default middlewares.
+ public static System.Net.Http.HttpClient Create(IAuthenticationProvider authenticationProvider = default) {
+ var defaultHandlers = CreateDefaultHandlers(authenticationProvider);
+ var handler = ChainHandlersCollectionAndGetFirstLink(defaultHandlers.ToArray());
+ return handler != null ? new System.Net.Http.HttpClient(handler) : new System.Net.Http.HttpClient(); //TODO configure the default client options
+ }
+ ///
+ /// Creates a default set of middleware to be used by the .
+ ///
+ /// The to authenticate requests.
+ /// A list of the default handlers used by the client.
+ public static IList CreateDefaultHandlers(IAuthenticationProvider authenticationProvider = default)
+ {
+ return new List(); //TODO add the default middlewares when they are ready
+ }
+ ///
+ /// Creates a to use for the from the provided instances. Order matters.
+ ///
+ /// The instances to create the from.
+ /// The created .
+ public static DelegatingHandler ChainHandlersCollectionAndGetFirstLink(params DelegatingHandler[] handlers) {
+ if(handlers == null || !handlers.Any()) return default;
+ var handlersCount = handlers.Count();
+ for(var i = 0; i < handlersCount; i++) {
+ var handler = handlers[i];
+ var previousItemIndex = i - 1;
+ if(previousItemIndex >= 0) {
+ var previousHandler = handlers[previousItemIndex];
+ previousHandler.InnerHandler = handler;
+ }
+ }
+ return handlers.First();
+ }
+ }
+}
diff --git a/http/dotnet/httpclient/src/HttpCore.cs b/http/dotnet/httpclient/src/HttpCore.cs
index db276f4b48..8bfe6ce6d3 100644
--- a/http/dotnet/httpclient/src/HttpCore.cs
+++ b/http/dotnet/httpclient/src/HttpCore.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
@@ -28,7 +29,7 @@ public HttpCore(IAuthenticationProvider authenticationProvider, IParseNodeFactor
{
authProvider = authenticationProvider ?? throw new ArgumentNullException(nameof(authenticationProvider));
createdClient = httpClient == null;
- client = httpClient ?? new System.Net.Http.HttpClient();
+ client = httpClient ?? HttpClientBuilder.Create(authProvider);
pNodeFactory = parseNodeFactory ?? ParseNodeFactoryRegistry.DefaultInstance;
sWriterFactory = serializationWriterFactory ?? SerializationWriterFactoryRegistry.DefaultInstance;
}
@@ -128,6 +129,8 @@ private HttpRequestMessage GetRequestMessageFromRequestInfo(RequestInfo requestI
string.Empty)),
};
+ if(requestInfo.MiddlewareOptions.Any())
+ requestInfo.MiddlewareOptions.ToList().ForEach(x => message.Options.Set(new HttpRequestOptionsKey(x.GetType().FullName), x));
if(requestInfo.Headers?.Any() ?? false)
requestInfo.Headers.Where(x => !contentTypeHeaderName.Equals(x.Key, StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => message.Headers.Add(x.Key, x.Value));
if(requestInfo.Content != null) {
diff --git a/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj b/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
index 2af059605f..f2b8fbbeac 100644
--- a/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
+++ b/http/dotnet/httpclient/src/Microsoft.Kiota.Http.HttpClient.csproj
@@ -4,11 +4,11 @@
net5.0
true
https://github.com/microsoft/kiota
- 1.0.3
+ 1.0.4
-
+
diff --git a/http/java/okhttp/lib/build.gradle b/http/java/okhttp/lib/build.gradle
index 6604725815..ee79fd1316 100644
--- a/http/java/okhttp/lib/build.gradle
+++ b/http/java/okhttp/lib/build.gradle
@@ -36,7 +36,7 @@ dependencies {
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:30.1.1-jre'
api 'com.squareup.okhttp3:okhttp:4.9.1'
- api 'com.microsoft.kiota:kiota-abstractions:1.0.13'
+ api 'com.microsoft.kiota:kiota-abstractions:1.0.14'
}
publishing {
@@ -53,7 +53,7 @@ publishing {
publications {
gpr(MavenPublication) {
artifactId 'kiota-http-okhttp'
- version '1.0.3'
+ version '1.0.4'
from(components.java)
}
}
diff --git a/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
index a8a250cfa7..5289201a13 100644
--- a/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
+++ b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/HttpCore.java
@@ -1,6 +1,3 @@
-/*
- * This Java source file was generated by the Gradle 'init' task.
- */
package com.microsoft.kiota.http;
import java.io.IOException;
@@ -18,6 +15,7 @@
import com.microsoft.kiota.ApiClientBuilder;
import com.microsoft.kiota.RequestInfo;
+import com.microsoft.kiota.MiddlewareOption;
import com.microsoft.kiota.ResponseHandler;
import com.microsoft.kiota.AuthenticationProvider;
import com.microsoft.kiota.serialization.ParseNodeFactoryRegistry;
@@ -55,7 +53,7 @@ public HttpCore(@Nonnull final AuthenticationProvider authenticationProvider, @N
public HttpCore(@Nonnull final AuthenticationProvider authenticationProvider, @Nullable final ParseNodeFactory parseNodeFactory, @Nullable final SerializationWriterFactory serializationWriterFactory, @Nullable final OkHttpClient client) {
this.authProvider = Objects.requireNonNull(authenticationProvider, "parameter authenticationProvider cannot be null");
if(client == null) {
- this.client = new OkHttpClient.Builder().build();
+ this.client = OkHttpClientBuilder.Create(this.authProvider).build();
} else {
this.client = client;
}
@@ -210,6 +208,9 @@ public void writeTo(BufferedSink sink) throws IOException {
for (final Map.Entry header : requestInfo.headers.entrySet()) {
requestBuilder.addHeader(header.getKey(), header.getValue());
}
+ for(final MiddlewareOption option : requestInfo.getMiddlewareOptions()) {
+ requestBuilder.tag(option);
+ }
return requestBuilder.build();
}
}
diff --git a/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/OkHttpClientBuilder.java b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/OkHttpClientBuilder.java
new file mode 100644
index 0000000000..4eea3c6217
--- /dev/null
+++ b/http/java/okhttp/lib/src/main/java/com/microsoft/kiota/http/OkHttpClientBuilder.java
@@ -0,0 +1,21 @@
+package com.microsoft.kiota.http;
+
+import com.microsoft.kiota.AuthenticationProvider;
+
+import okhttp3.OkHttpClient;
+
+import javax.annotation.Nullable;
+
+/** This class is used to build the HttpClient instance used by the core service. */
+public class OkHttpClientBuilder {
+ private OkHttpClientBuilder() { }
+ /**
+ * Creates an OkHttpClient Builder with the default configuration and middlewares including a authentention middleware using the {@link AuthenticationProvider} if provided.
+ * @param authenticationProvider the authentication provider used to authenticate the requests.
+ * @return an OkHttpClient Builder instance.
+ */
+ public static OkHttpClient.Builder Create(@Nullable final AuthenticationProvider authenticationProvider) {
+ return new OkHttpClient.Builder(); //TODO configure the default client options.
+ //TODO add the default middlewares when they are ready
+ }
+}
\ No newline at end of file
diff --git a/http/typescript/fetch/package-lock.json b/http/typescript/fetch/package-lock.json
index cf36fbd779..320dd3e81d 100644
--- a/http/typescript/fetch/package-lock.json
+++ b/http/typescript/fetch/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-http-fetch",
- "version": "1.0.3",
+ "version": "1.0.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/http/typescript/fetch/package.json b/http/typescript/fetch/package.json
index 134bb295c0..bd5e4fa32f 100644
--- a/http/typescript/fetch/package.json
+++ b/http/typescript/fetch/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/kiota-http-fetch",
- "version": "1.0.3",
+ "version": "1.0.4",
"description": "Kiota HttpCore implementation with fetch",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
"registry": "https://npm.pkg.github.com"
},
"dependencies": {
- "@microsoft/kiota-abstractions": "^1.0.13",
+ "@microsoft/kiota-abstractions": "^1.0.14",
"cross-fetch": "^3.1.4",
"web-streams-polyfill": "^3.1.0"
},
diff --git a/http/typescript/fetch/src/httpClient.ts b/http/typescript/fetch/src/httpClient.ts
new file mode 100644
index 0000000000..98a59d4a58
--- /dev/null
+++ b/http/typescript/fetch/src/httpClient.ts
@@ -0,0 +1,53 @@
+import { Middleware } from "./middleware";
+import { fetch } from 'cross-fetch';
+import { MiddlewareOption } from "@microsoft/kiota-abstractions";
+
+/** Default fetch client with options and a middleware pipleline for requests execution. */
+export class HttpClient {
+ /**
+ * Instantiates a new HttpClient.
+ * @param middlewares middlewares to be used for requests execution.
+ * @param defaultRequestSettings default request settings to be used for requests execution.
+ */
+ public constructor(private readonly middlewares: Middleware[] = HttpClient.getDefaultMiddlewares(), private readonly defaultRequestSettings: RequestInit = HttpClient.getDefaultRequestSettings()) {
+ this.middlewares = [...this.middlewares, new FetchMiddleware()];
+ this.middlewares.forEach((middleware, idx) => {
+ if(idx < this.middlewares.length)
+ middleware.next = this.middlewares[idx + 1];
+ });
+ }
+ /**
+ * Executes a request and returns a promise resolving the response.
+ * @param url the request url.
+ * @param options request options.
+ * @returns the promise resolving the response.
+ */
+ public fetch(url: string, options?: RequestInit, middlewareOptions?: MiddlewareOption[]): Promise {
+ const finalOptions = {...this.defaultRequestSettings, ...options} as RequestInit;
+ if(this.middlewares.length > 0 && this.middlewares[0])
+ return this.middlewares[0].execute(url, finalOptions, middlewareOptions);
+ else
+ throw new Error("No middlewares found");
+ }
+ /**
+ * Gets the default middlewares in use for the client.
+ * @returns the default middlewares.
+ */
+ public static getDefaultMiddlewares(): Middleware[] {
+ return []; //TODO add default middlewares
+ }
+ /**
+ * Gets the default request settings to be used for the client.
+ * @returns the default request settings.
+ */
+ public static getDefaultRequestSettings(): RequestInit {
+ return {}; //TODO add default request settings
+ }
+}
+/** Default middleware executing a request. Internal use only. */
+class FetchMiddleware implements Middleware {
+ next: Middleware | undefined;
+ public execute(url: string, req: RequestInit, _?: MiddlewareOption[]): Promise {
+ return fetch(url, req);
+ }
+}
\ No newline at end of file
diff --git a/http/typescript/fetch/src/httpCore.ts b/http/typescript/fetch/src/httpCore.ts
index 6c48b6f230..f51091ee75 100644
--- a/http/typescript/fetch/src/httpCore.ts
+++ b/http/typescript/fetch/src/httpCore.ts
@@ -1,21 +1,33 @@
import { AuthenticationProvider, HttpCore as IHttpCore, Parsable, ParseNodeFactory, RequestInfo, ResponseHandler, ParseNodeFactoryRegistry, enableBackingStoreForParseNodeFactory, SerializationWriterFactoryRegistry, enableBackingStoreForSerializationWriterFactory, SerializationWriterFactory } from '@microsoft/kiota-abstractions';
-import { fetch, Headers as FetchHeadersCtor } from 'cross-fetch';
+import { Headers as FetchHeadersCtor } from 'cross-fetch';
import { ReadableStream } from 'web-streams-polyfill';
import { URLSearchParams } from 'url';
+import { HttpClient } from './httpClient';
export class HttpCore implements IHttpCore {
- private _serializationWriterFactory: SerializationWriterFactory;
public getSerializationWriterFactory(): SerializationWriterFactory {
- return this._serializationWriterFactory;
+ return this.serializationWriterFactory;
}
private static readonly authorizationHeaderKey = "Authorization";
/**
- *
+ * Instantiates a new http core service
+ * @param authenticationProvider the authentication provider to use.
+ * @param parseNodeFactory the parse node factory to deserialize responses.
+ * @param serializationWriterFactory the serialization writer factory to use to serialize request bodies.
+ * @param httpClient the http client to use to execute requests.
*/
- public constructor(public readonly authenticationProvider: AuthenticationProvider, private parseNodeFactory: ParseNodeFactory = ParseNodeFactoryRegistry.defaultInstance, serializationWriterFactory: SerializationWriterFactory = SerializationWriterFactoryRegistry.defaultInstance) {
+ public constructor(public readonly authenticationProvider: AuthenticationProvider, private parseNodeFactory: ParseNodeFactory = ParseNodeFactoryRegistry.defaultInstance, private serializationWriterFactory: SerializationWriterFactory = SerializationWriterFactoryRegistry.defaultInstance, private readonly httpClient: HttpClient = new HttpClient()) {
if(!authenticationProvider) {
throw new Error('authentication provider cannot be null');
}
- this._serializationWriterFactory = serializationWriterFactory;
+ if(!parseNodeFactory) {
+ throw new Error('parse node factory cannot be null');
+ }
+ if(!serializationWriterFactory) {
+ throw new Error('serialization writer factory cannot be null');
+ }
+ if(!httpClient) {
+ throw new Error('http client cannot be null');
+ }
}
private getResponseContentType = (response: Response): string | undefined => {
const header = response.headers.get("content-type")?.toLowerCase();
@@ -31,7 +43,7 @@ export class HttpCore implements IHttpCore {
await this.addBearerIfNotPresent(requestInfo);
const request = this.getRequestFromRequestInfo(requestInfo);
- const response = await fetch(this.getRequestUrl(requestInfo), request);
+ const response = await this.httpClient.fetch(this.getRequestUrl(requestInfo), request);
if(responseHandler) {
return await responseHandler.handleResponseAsync(response);
} else {
@@ -52,7 +64,7 @@ export class HttpCore implements IHttpCore {
await this.addBearerIfNotPresent(requestInfo);
const request = this.getRequestFromRequestInfo(requestInfo);
- const response = await fetch(this.getRequestUrl(requestInfo), request);
+ const response = await this.httpClient.fetch(this.getRequestUrl(requestInfo), request);
if(responseHandler) {
return await responseHandler.handleResponseAsync(response);
} else {
@@ -100,15 +112,15 @@ export class HttpCore implements IHttpCore {
await this.addBearerIfNotPresent(requestInfo);
const request = this.getRequestFromRequestInfo(requestInfo);
- const response = await fetch(this.getRequestUrl(requestInfo), request);
+ const response = await this.httpClient.fetch(this.getRequestUrl(requestInfo), request);
if(responseHandler) {
return await responseHandler.handleResponseAsync(response);
}
}
public enableBackingStore = (): void => {
this.parseNodeFactory = enableBackingStoreForParseNodeFactory(this.parseNodeFactory);
- this._serializationWriterFactory = enableBackingStoreForSerializationWriterFactory(this._serializationWriterFactory);
- if(!this._serializationWriterFactory || !this.parseNodeFactory)
+ this.serializationWriterFactory = enableBackingStoreForSerializationWriterFactory(this.serializationWriterFactory);
+ if(!this.serializationWriterFactory || !this.parseNodeFactory)
throw new Error("unable to enable backing store");
}
private addBearerIfNotPresent = async (requestInfo: RequestInfo): Promise => {
diff --git a/http/typescript/fetch/src/index.ts b/http/typescript/fetch/src/index.ts
index e6f69e7c19..01e1f085f8 100644
--- a/http/typescript/fetch/src/index.ts
+++ b/http/typescript/fetch/src/index.ts
@@ -1 +1,3 @@
-export * from './httpCore';
\ No newline at end of file
+export * from './httpCore';
+export * from './httpClient';
+export * from './middleware';
\ No newline at end of file
diff --git a/http/typescript/fetch/src/middleware.ts b/http/typescript/fetch/src/middleware.ts
new file mode 100644
index 0000000000..abb6ab84ee
--- /dev/null
+++ b/http/typescript/fetch/src/middleware.ts
@@ -0,0 +1,14 @@
+import { MiddlewareOption } from "@microsoft/kiota-abstractions";
+
+/** Defines the contract for a middleware in the request execution pipeline. */
+export interface Middleware {
+ /** Next middleware to be executed. The current middleware must execute it in its implementation. */
+ next: Middleware | undefined;
+ /**
+ * Main method of the middleware.
+ * @param req The request object.
+ * @param url The URL of the request.
+ * @return A promise that resolves to the response object.
+ */
+ execute(url: string, req: RequestInit, middlewareOptions?: MiddlewareOption[]): Promise;
+}
\ No newline at end of file
diff --git a/src/Kiota.Builder/CodeDOM/CodeMethod.cs b/src/Kiota.Builder/CodeDOM/CodeMethod.cs
index fb2c4fb180..5529fabce1 100644
--- a/src/Kiota.Builder/CodeDOM/CodeMethod.cs
+++ b/src/Kiota.Builder/CodeDOM/CodeMethod.cs
@@ -54,6 +54,14 @@ public bool IsSerializationMethod {
}
public List SerializerModules { get; set; }
public List DeserializerModules { get; set; }
+ ///
+ /// Indicates whether this method is an overload for another method.
+ ///
+ public bool IsOverload { get { return OriginalMethod != null; } }
+ ///
+ /// Provides a reference to the original method that this method is an overload of.
+ ///
+ public CodeMethod OriginalMethod { get; set; }
public object Clone()
{
@@ -72,6 +80,7 @@ public object Clone()
PathSegment = PathSegment?.Clone() as string,
SerializerModules = SerializerModules == null ? null : new (SerializerModules),
DeserializerModules = DeserializerModules == null ? null : new (DeserializerModules),
+ OriginalMethod = OriginalMethod
};
}
diff --git a/src/Kiota.Builder/CodeDOM/CodeParameter.cs b/src/Kiota.Builder/CodeDOM/CodeParameter.cs
index 703ee7a679..be3f1480fa 100644
--- a/src/Kiota.Builder/CodeDOM/CodeParameter.cs
+++ b/src/Kiota.Builder/CodeDOM/CodeParameter.cs
@@ -12,7 +12,9 @@ public enum CodeParameterKind
RequestBody,
SetterValue,
HttpCore,
- CurrentPath
+ CurrentPath,
+ Options,
+ Serializer
}
public class CodeParameter : CodeTerminal, ICloneable, IDocumentedElement
diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs
index b474ebd966..19f1b1e642 100644
--- a/src/Kiota.Builder/KiotaBuilder.cs
+++ b/src/Kiota.Builder/KiotaBuilder.cs
@@ -575,6 +575,14 @@ private void AddRequestBuilderMethodParameters(OpenApiUrlTreeNode currentNode, O
};
headersParam.Type = new CodeType(headersParam) { Name = "IDictionary", ActionOf = true, IsExternal = true };
method.AddParameter(headersParam);
+ var optionsParam = new CodeParameter(method) {
+ Name = "o",
+ Optional = true,
+ ParameterKind = CodeParameterKind.Options,
+ Description = "Request options for HTTP middlewares"
+ };
+ optionsParam.Type = new CodeType(optionsParam) { Name = "IEnumerable", ActionOf = false, IsExternal = true };
+ method.AddParameter(optionsParam);
}
private IEnumerable GetAllNamespaceNamesForModelByReferenceId(string referenceId) {
if(string.IsNullOrEmpty(referenceId)) throw new ArgumentNullException(nameof(referenceId));
@@ -772,7 +780,8 @@ private void AddSerializationMembers(CodeClass model, bool includeAdditionalProp
serializeMethod.ReturnType = new CodeType(serializeMethod) { Name = voidType, IsNullable = false, IsExternal = true };
var parameter = new CodeParameter(serializeMethod) {
Name = "writer",
- Description = "Serialization writer to use to serialize this model"
+ Description = "Serialization writer to use to serialize this model",
+ ParameterKind = CodeParameterKind.Serializer,
};
parameter.Type = new CodeType(parameter) { Name = "ISerializationWriter", IsExternal = true, IsNullable = false };
serializeMethod.AddParameter(parameter);
diff --git a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
index 8e5a286276..2f69c2e9bc 100644
--- a/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
+++ b/src/Kiota.Builder/Refiners/CommonLanguageRefiner.cs
@@ -465,5 +465,16 @@ protected static void CrawlTree(CodeElement currentElement, Action
foreach(var childElement in currentElement.GetChildElements())
function.Invoke(childElement);
}
+ protected static void CorrectCoreType(CodeElement currentElement, Action correctMethodType, Action correctPropertyType) {
+ switch(currentElement) {
+ case CodeProperty property:
+ correctPropertyType.Invoke(property);
+ break;
+ case CodeMethod method:
+ correctMethodType.Invoke(method);
+ break;
+ }
+ CrawlTree(currentElement, x => CorrectCoreType(x, correctMethodType, correctPropertyType));
+ }
}
}
diff --git a/src/Kiota.Builder/Refiners/JavaRefiner.cs b/src/Kiota.Builder/Refiners/JavaRefiner.cs
index 867ec220aa..f5c15164b3 100644
--- a/src/Kiota.Builder/Refiners/JavaRefiner.cs
+++ b/src/Kiota.Builder/Refiners/JavaRefiner.cs
@@ -17,7 +17,7 @@ public override void Refine(CodeNamespace generatedCode)
FixReferencesToEntityType(generatedCode);
AddPropertiesAndMethodTypesImports(generatedCode, true, false, true);
AddDefaultImports(generatedCode, defaultNamespaces, defaultNamespacesForModels, defaultNamespacesForRequestBuilders, defaultSymbolsForApiClient);
- CorrectCoreType(generatedCode);
+ CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType);
PatchHeaderParametersType(generatedCode);
AddListImport(generatedCode);
AddParsableInheritanceForModelClasses(generatedCode);
@@ -78,11 +78,13 @@ private static void AddListImport(CodeElement currentElement) {
new ("RequestInfo", "com.microsoft.kiota"),
new ("ResponseHandler", "com.microsoft.kiota"),
new ("QueryParametersBase", "com.microsoft.kiota"),
+ new ("MiddlewareOption", "com.microsoft.kiota"),
new ("Map", "java.util"),
new ("URI", "java.net"),
new ("URISyntaxException", "java.net"),
new ("InputStream", "java.io"),
new ("Function", "java.util.function"),
+ new ("Collection", "java.util"),
};
private static readonly Tuple[] defaultNamespaces = new Tuple[] {
new ("SerializationWriter", "com.microsoft.kiota.serialization"),
@@ -99,43 +101,43 @@ private static void AddListImport(CodeElement currentElement) {
new ("SerializationWriterFactoryRegistry", "com.microsoft.kiota.serialization"),
new ("ParseNodeFactoryRegistry", "com.microsoft.kiota.serialization"),
};
- private static void CorrectCoreType(CodeElement currentElement) {
- if (currentElement is CodeProperty currentProperty && currentProperty.Type != null) {
- if(currentProperty.IsOfKind(CodePropertyKind.HttpCore))
+ private static void CorrectPropertyType(CodeProperty currentProperty) {
+ if(currentProperty.IsOfKind(CodePropertyKind.HttpCore))
currentProperty.Type.Name = "HttpCore";
- else if(currentProperty.IsOfKind(CodePropertyKind.BackingStore))
- currentProperty.Type.Name = currentProperty.Type.Name[1..]; // removing the "I"
- else if("DateTimeOffset".Equals(currentProperty.Type.Name, StringComparison.OrdinalIgnoreCase)) {
- currentProperty.Type.Name = $"OffsetDateTime";
- var nUsing = new CodeUsing(currentProperty.Parent) {
- Name = "OffsetDateTime",
- };
- nUsing.Declaration = new CodeType(nUsing) {
- Name = "java.time",
- IsExternal = true,
- };
- (currentProperty.Parent as CodeClass).AddUsing(nUsing);
- } else if(currentProperty.IsOfKind(CodePropertyKind.AdditionalData)) {
- currentProperty.Type.Name = "Map";
- currentProperty.DefaultValue = "new HashMap<>()";
- }
+ else if(currentProperty.IsOfKind(CodePropertyKind.BackingStore))
+ currentProperty.Type.Name = currentProperty.Type.Name[1..]; // removing the "I"
+ else if("DateTimeOffset".Equals(currentProperty.Type.Name, StringComparison.OrdinalIgnoreCase)) {
+ currentProperty.Type.Name = $"OffsetDateTime";
+ var nUsing = new CodeUsing(currentProperty.Parent) {
+ Name = "OffsetDateTime",
+ };
+ nUsing.Declaration = new CodeType(nUsing) {
+ Name = "java.time",
+ IsExternal = true,
+ };
+ (currentProperty.Parent as CodeClass).AddUsing(nUsing);
+ } else if(currentProperty.IsOfKind(CodePropertyKind.AdditionalData)) {
+ currentProperty.Type.Name = "Map";
+ currentProperty.DefaultValue = "new HashMap<>()";
}
- if (currentElement is CodeMethod currentMethod) {
+ }
+ private static void CorrectMethodType(CodeMethod currentMethod) {
+ if(currentMethod.IsOfKind(CodeMethodKind.RequestExecutor, CodeMethodKind.RequestGenerator)) {
if(currentMethod.IsOfKind(CodeMethodKind.RequestExecutor))
- currentMethod.Parameters.Where(x => x.Type.Name.Equals("IResponseHandler")).ToList().ForEach(x => x.Type.Name = "ResponseHandler");
- else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
- currentMethod.Parameters.Where(x => x.Type.Name.Equals("ISerializationWriter")).ToList().ForEach(x => x.Type.Name = "SerializationWriter");
- else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer)) {
- currentMethod.ReturnType.Name = $"Map>";
- currentMethod.Name = "getFieldDeserializers";
- }
- else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor))
- currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.HttpCore))
- .Where(x => x.Type.Name.StartsWith("I", StringComparison.InvariantCultureIgnoreCase))
- .ToList()
- .ForEach(x => x.Type.Name = x.Type.Name[1..]); // removing the "I"
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.ResponseHandler) && x.Type.Name.StartsWith("i", StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => x.Type.Name = x.Type.Name[1..]);
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Options)).ToList().ForEach(x => x.Type.Name = "Collection");
+ }
+ else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Serializer) && x.Type.Name.StartsWith("i", StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => x.Type.Name = x.Type.Name[1..]);
+ else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer)) {
+ currentMethod.ReturnType.Name = $"Map>";
+ currentMethod.Name = "getFieldDeserializers";
}
- CrawlTree(currentElement, CorrectCoreType);
+ else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor))
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.HttpCore))
+ .Where(x => x.Type.Name.StartsWith("I", StringComparison.OrdinalIgnoreCase))
+ .ToList()
+ .ForEach(x => x.Type.Name = x.Type.Name[1..]); // removing the "I"
}
private static void AddRequireNonNullImports(CodeElement currentElement) {
if(currentElement is CodeMethod currentMethod && currentMethod.Parameters.Any(x => !x.Optional)) {
@@ -157,17 +159,21 @@ private static void AndInsertOverrideMethodForRequestExecutorsAndBuilders(CodeEl
if(codeMethods.Any()) {
var originalExecutorMethods = codeMethods.Where(x => x.IsOfKind(CodeMethodKind.RequestExecutor));
var executorMethodsToAdd = originalExecutorMethods
- .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter))
+ .Select(x => GetMethodClone(x, CodeParameterKind.ResponseHandler))
.Union(originalExecutorMethods
- .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter, CodeParameterKind.Headers)))
+ .Select(x => GetMethodClone(x, CodeParameterKind.Options, CodeParameterKind.ResponseHandler)))
.Union(originalExecutorMethods
- .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter, CodeParameterKind.Headers, CodeParameterKind.ResponseHandler)))
+ .Select(x => GetMethodClone(x, CodeParameterKind.Headers, CodeParameterKind.Options, CodeParameterKind.ResponseHandler)))
+ .Union(originalExecutorMethods
+ .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter, CodeParameterKind.Headers, CodeParameterKind.Options, CodeParameterKind.ResponseHandler)))
.Where(x => x != null);
var originalGeneratorMethods = codeMethods.Where(x => x.IsOfKind(CodeMethodKind.RequestGenerator));
var generatorMethodsToAdd = originalGeneratorMethods
- .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter))
+ .Select(x => GetMethodClone(x, CodeParameterKind.Options))
+ .Union(originalGeneratorMethods
+ .Select(x => GetMethodClone(x, CodeParameterKind.Headers, CodeParameterKind.Options)))
.Union(originalGeneratorMethods
- .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter, CodeParameterKind.Headers)))
+ .Select(x => GetMethodClone(x, CodeParameterKind.QueryParameter, CodeParameterKind.Headers, CodeParameterKind.Options)))
.Where(x => x != null);
if(executorMethodsToAdd.Any() || generatorMethodsToAdd.Any())
currentClass.AddMethod(executorMethodsToAdd.Union(generatorMethodsToAdd).ToArray());
@@ -187,6 +193,7 @@ private static CodeMethod GetMethodClone(CodeMethod currentMethod, params CodePa
if(currentMethod.Parameters.Any(x => parameterTypesToExclude.Contains(x.ParameterKind))) {
var cloneMethod = currentMethod.Clone() as CodeMethod;
cloneMethod.Parameters.RemoveAll(x => parameterTypesToExclude.Contains(x.ParameterKind));
+ cloneMethod.OriginalMethod = currentMethod;
return cloneMethod;
}
else return null;
diff --git a/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs b/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs
index 42ba71d12a..7f3f2016b9 100644
--- a/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs
+++ b/src/Kiota.Builder/Refiners/TypeScriptRefiner.cs
@@ -10,7 +10,7 @@ public override void Refine(CodeNamespace generatedCode)
PatchResponseHandlerType(generatedCode);
AddDefaultImports(generatedCode, Array.Empty>(), defaultNamespacesForModels, defaultNamespacesForRequestBuilders, defaultSymbolsForApiClient);
ReplaceIndexersByMethodsWithParameter(generatedCode, generatedCode, "ById");
- CorrectCoreType(generatedCode);
+ CorrectCoreType(generatedCode, CorrectMethodType, CorrectPropertyType);
CorrectCoreTypesForBackingStoreUsings(generatedCode, "@microsoft/kiota-abstractions");
FixReferencesToEntityType(generatedCode);
AddPropertiesAndMethodTypesImports(generatedCode, true, true, true);
@@ -42,6 +42,7 @@ private static void AddParsableInheritanceForModelClasses(CodeElement currentEle
new ("HttpMethod", "@microsoft/kiota-abstractions"),
new ("RequestInfo", "@microsoft/kiota-abstractions"),
new ("ResponseHandler", "@microsoft/kiota-abstractions"),
+ new ("MiddlewareOption", "@microsoft/kiota-abstractions"),
};
private static readonly Tuple[] defaultNamespacesForModels = new Tuple[] {
new ("SerializationWriter", "@microsoft/kiota-abstractions"),
@@ -55,35 +56,33 @@ private static void AddParsableInheritanceForModelClasses(CodeElement currentEle
new ("SerializationWriterFactoryRegistry", "@microsoft/kiota-abstractions"),
new ("ParseNodeFactoryRegistry", "@microsoft/kiota-abstractions"),
};
- private static void CorrectCoreType(CodeElement currentElement) {
- if (currentElement is CodeProperty currentProperty) {
- if(currentProperty.IsOfKind(CodePropertyKind.HttpCore))
- currentProperty.Type.Name = "HttpCore";
- else if(currentProperty.IsOfKind(CodePropertyKind.BackingStore))
- currentProperty.Type.Name = currentProperty.Type.Name[1..]; // removing the "I"
- else if("DateTimeOffset".Equals(currentProperty.Type.Name, StringComparison.OrdinalIgnoreCase))
- currentProperty.Type.Name = $"Date";
- else if(currentProperty.IsOfKind(CodePropertyKind.AdditionalData)) {
- currentProperty.Type.Name = "Map";
- currentProperty.DefaultValue = "new Map()";
- }
+ private static void CorrectPropertyType(CodeProperty currentProperty) {
+ if(currentProperty.IsOfKind(CodePropertyKind.HttpCore))
+ currentProperty.Type.Name = "HttpCore";
+ else if(currentProperty.IsOfKind(CodePropertyKind.BackingStore))
+ currentProperty.Type.Name = currentProperty.Type.Name[1..]; // removing the "I"
+ else if("DateTimeOffset".Equals(currentProperty.Type.Name, StringComparison.OrdinalIgnoreCase))
+ currentProperty.Type.Name = $"Date";
+ else if(currentProperty.IsOfKind(CodePropertyKind.AdditionalData)) {
+ currentProperty.Type.Name = "Map";
+ currentProperty.DefaultValue = "new Map()";
}
- if (currentElement is CodeMethod currentMethod) {
+ }
+ private static void CorrectMethodType(CodeMethod currentMethod) {
+ if(currentMethod.IsOfKind(CodeMethodKind.RequestExecutor, CodeMethodKind.RequestGenerator)) {
if(currentMethod.IsOfKind(CodeMethodKind.RequestExecutor))
- currentMethod.Parameters.Where(x => x.Type.Name.Equals("IResponseHandler")).ToList().ForEach(x => x.Type.Name = "ResponseHandler");
- else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
- currentMethod.Parameters.Where(x => x.Type.Name.Equals("ISerializationWriter")).ToList().ForEach(x => x.Type.Name = "SerializationWriter");
- else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer))
- currentMethod.ReturnType.Name = $"Map void>";
- else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor))
- currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.HttpCore))
- .Where(x => x.Type.Name.StartsWith("I", StringComparison.InvariantCultureIgnoreCase))
- .ToList()
- .ForEach(x => x.Type.Name = x.Type.Name[1..]); // removing the "I"
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.ResponseHandler) && x.Type.Name.StartsWith("i", StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => x.Type.Name = x.Type.Name[1..]);
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Options)).ToList().ForEach(x => x.Type.Name = "MiddlewareOption[]");
}
-
-
- CrawlTree(currentElement, CorrectCoreType);
+ else if(currentMethod.IsOfKind(CodeMethodKind.Serializer))
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.Serializer) && x.Type.Name.StartsWith("i", StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => x.Type.Name = x.Type.Name[1..]);
+ else if(currentMethod.IsOfKind(CodeMethodKind.Deserializer))
+ currentMethod.ReturnType.Name = $"Map void>";
+ else if(currentMethod.IsOfKind(CodeMethodKind.ClientConstructor))
+ currentMethod.Parameters.Where(x => x.IsOfKind(CodeParameterKind.HttpCore))
+ .Where(x => x.Type.Name.StartsWith("I", StringComparison.InvariantCultureIgnoreCase))
+ .ToList()
+ .ForEach(x => x.Type.Name = x.Type.Name[1..]); // removing the "I"
}
private static void PatchResponseHandlerType(CodeElement current) {
if(current is CodeMethod currentMethod && currentMethod.Name.Equals("defaultResponseHandler", StringComparison.OrdinalIgnoreCase))
diff --git a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
index 35adae3f80..01e8166a03 100644
--- a/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/CSharp/CodeMethodWriter.cs
@@ -27,6 +27,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
var requestBodyParam = codeElement.Parameters.OfKind(CodeParameterKind.RequestBody);
var queryStringParam = codeElement.Parameters.OfKind(CodeParameterKind.QueryParameter);
var headersParam = codeElement.Parameters.OfKind(CodeParameterKind.Headers);
+ var optionsParam = codeElement.Parameters.OfKind(CodeParameterKind.Options);
foreach(var parameter in codeElement.Parameters.Where(x => !x.Optional).OrderBy(x => x.Name)) {
if(nameof(String).Equals(parameter.Type.Name, StringComparison.OrdinalIgnoreCase))
writer.WriteLine($"if(string.IsNullOrEmpty({parameter.Name})) throw new ArgumentNullException(nameof({parameter.Name}));");
@@ -38,10 +39,10 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
WriteSerializerBody(inherits, parentClass, writer);
break;
case CodeMethodKind.RequestGenerator:
- WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, writer);
+ WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer);
break;
case CodeMethodKind.RequestExecutor:
- WriteRequestExecutorBody(codeElement, requestBodyParam, queryStringParam, headersParam, isVoid, returnType, writer);
+ WriteRequestExecutorBody(codeElement, new List { requestBodyParam, queryStringParam, headersParam, optionsParam }, isVoid, returnType, writer);
break;
case CodeMethodKind.Deserializer:
WriteDeserializerBody(codeElement, parentClass, writer);
@@ -139,7 +140,7 @@ private string GetDeserializationMethodName(CodeTypeBase propType) {
return $"GetObjectValue<{propertyType.ToFirstCharacterUpperCase()}>";
}
}
- private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, bool isVoid, string returnType, LanguageWriter writer) {
+ private void WriteRequestExecutorBody(CodeMethod codeElement, IEnumerable parameters, bool isVoid, string returnType, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
var isStream = conventions.StreamTypeName.Equals(returnType, StringComparison.OrdinalIgnoreCase);
@@ -148,19 +149,16 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
.OfType()
.FirstOrDefault(x => x.IsOfKind(CodeMethodKind.RequestGenerator) && x.HttpMethod == codeElement.HttpMethod)
?.Name;
- writer.WriteLine($"var requestInfo = {generatorMethodName}(");
- writer.IncreaseIndent();
- writer.WriteLine(new List { requestBodyParam?.Name, queryStringParam?.Name, headersParam?.Name }.Where(x => x != null).Aggregate((x,y) => $"{x}, {y}"));
- writer.DecreaseIndent();
- writer.WriteLines(");",
- $"{(isVoid ? string.Empty : "return ")}await HttpCore.{GetSendRequestMethodName(isVoid, isStream, returnType)}(requestInfo, responseHandler);");
-
+ var parametersList = parameters.Select(x => x?.Name).Where(x => x != null).Aggregate((x,y) => $"{x}, {y}");
+ writer.WriteLine($"var requestInfo = {generatorMethodName}({parametersList});");
+ writer.WriteLine($"{(isVoid ? string.Empty : "return ")}await HttpCore.{GetSendRequestMethodName(isVoid, isStream, returnType)}(requestInfo, responseHandler);");
}
- private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, LanguageWriter writer) {
+ private const string _requestInfoVarName = "requestInfo";
+ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
var operationName = codeElement.HttpMethod.ToString();
- writer.WriteLine("var requestInfo = new RequestInfo {");
+ writer.WriteLine($"var {_requestInfoVarName} = new RequestInfo {{");
writer.IncreaseIndent();
writer.WriteLines($"HttpMethod = HttpMethod.{operationName?.ToUpperInvariant()},",
$"URI = new Uri({conventions.CurrentPathPropertyName} + {conventions.PathSegmentPropertyName}),");
@@ -168,23 +166,24 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter req
writer.WriteLine("};");
if(requestBodyParam != null) {
if(requestBodyParam.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
- writer.WriteLine($"requestInfo.SetStreamContent({requestBodyParam.Name});");
+ writer.WriteLine($"{_requestInfoVarName}.SetStreamContent({requestBodyParam.Name});");
else
- writer.WriteLine($"requestInfo.SetContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
+ writer.WriteLine($"{_requestInfoVarName}.SetContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
}
if(queryStringParam != null) {
writer.WriteLine($"if ({queryStringParam.Name} != null) {{");
writer.IncreaseIndent();
writer.WriteLines($"var qParams = new {operationName?.ToFirstCharacterUpperCase()}QueryParameters();",
$"{queryStringParam.Name}.Invoke(qParams);",
- "qParams.AddQueryParameters(requestInfo.QueryParameters);");
+ $"qParams.AddQueryParameters({_requestInfoVarName}.QueryParameters);");
writer.DecreaseIndent();
writer.WriteLine("}");
}
- if(headersParam != null) {
- writer.WriteLines($"{headersParam.Name}?.Invoke(requestInfo.Headers);",
- "return requestInfo;");
- }
+ if(headersParam != null)
+ writer.WriteLine($"{headersParam.Name}?.Invoke({_requestInfoVarName}.Headers);");
+ if(optionsParam != null)
+ writer.WriteLine($"{_requestInfoVarName}.AddMiddlewareOptions({optionsParam.Name}?.ToArray());");
+ writer.WriteLine($"return {_requestInfoVarName};");
}
private void WriteSerializerBody(bool shouldHide, CodeClass parentClass, LanguageWriter writer) {
var additionalDataProperty = parentClass.GetChildElements(true).OfType().FirstOrDefault(x => x.IsOfKind(CodePropertyKind.AdditionalData));
diff --git a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
index b70bb19c7c..ab607349e7 100644
--- a/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/Java/CodeMethodWriter.cs
@@ -33,6 +33,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
var requestBodyParam = codeElement.Parameters.OfKind(CodeParameterKind.RequestBody);
var queryStringParam = codeElement.Parameters.OfKind(CodeParameterKind.QueryParameter);
var headersParam = codeElement.Parameters.OfKind(CodeParameterKind.Headers);
+ var optionsParam = codeElement.Parameters.OfKind(CodeParameterKind.Options);
foreach(var parameter in codeElement.Parameters.Where(x => !x.Optional).OrderBy(x => x.Name)) {
writer.WriteLine($"Objects.requireNonNull({parameter.Name});");
}
@@ -46,11 +47,14 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
case CodeMethodKind.IndexerBackwardCompatibility:
WriteIndexerBody(codeElement, writer, returnType);
break;
- case CodeMethodKind.RequestGenerator:
- WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, writer);
+ case CodeMethodKind.RequestGenerator when codeElement.IsOverload:
+ WriteGeneratorMethodCall(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer, "return ");
+ break;
+ case CodeMethodKind.RequestGenerator when !codeElement.IsOverload:
+ WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer);
break;
case CodeMethodKind.RequestExecutor:
- WriteRequestExecutorBody(codeElement, requestBodyParam, queryStringParam, headersParam, returnType, writer);
+ WriteRequestExecutorBody(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, returnType, writer);
break;
case CodeMethodKind.Getter:
WriteGetterBody(codeElement, writer, parentClass);
@@ -161,25 +165,11 @@ private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass
}
writer.WriteLine("}};");
}
- private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, string returnType, LanguageWriter writer) {
+ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, string returnType, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
-
- var generatorMethodName = (codeElement.Parent as CodeClass)
- .GetChildElements(true)
- .OfType()
- .FirstOrDefault(x => x.IsOfKind(CodeMethodKind.RequestGenerator) && x.HttpMethod == codeElement.HttpMethod)
- ?.Name
- ?.ToFirstCharacterLowerCase();
writer.WriteLine("try {");
writer.IncreaseIndent();
- writer.WriteLine($"final RequestInfo requestInfo = {generatorMethodName}(");
- var requestInfoParameters = new List { requestBodyParam?.Name, queryStringParam?.Name, headersParam?.Name }.Where(x => x != null);
- if(requestInfoParameters.Any()) {
- writer.IncreaseIndent();
- writer.WriteLine(requestInfoParameters.Aggregate((x,y) => $"{x}, {y}"));
- writer.DecreaseIndent();
- }
- writer.WriteLine(");");
+ WriteGeneratorMethodCall(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer, $"final RequestInfo {requestInfoVarName} = ");
var sendMethodName = conventions.PrimitiveTypes.Contains(returnType) ? "sendPrimitiveAsync" : "sendAsync";
if(codeElement.Parameters.Any(x => x.IsOfKind(CodeParameterKind.ResponseHandler)))
writer.WriteLine($"return this.httpCore.{sendMethodName}(requestInfo, {returnType}.class, responseHandler);");
@@ -192,10 +182,31 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
writer.DecreaseIndent();
writer.WriteLine("}");
}
- private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, LanguageWriter writer) {
+ private const string requestInfoVarName = "requestInfo";
+ private static void WriteGeneratorMethodCall(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer, string prefix) {
+ var generatorMethodName = (codeElement.Parent as CodeClass)
+ .GetChildElements(true)
+ .OfType()
+ .FirstOrDefault(x => x.IsOfKind(CodeMethodKind.RequestGenerator) && x.HttpMethod == codeElement.HttpMethod)
+ ?.Name
+ ?.ToFirstCharacterLowerCase();
+ var paramsList = new List { requestBodyParam, queryStringParam, headersParam, optionsParam };
+ var requestInfoParameters = paramsList.Where(x => x != null)
+ .Select(x => x.Name)
+ .ToList();
+ var shouldSkipBodyParam = requestBodyParam == null && (codeElement.HttpMethod == HttpMethod.Get || codeElement.HttpMethod == HttpMethod.Delete);
+ var skipIndex = shouldSkipBodyParam ? 1 : 0;
+ if(codeElement.IsOverload && !codeElement.OriginalMethod.Parameters.Any(x => x.IsOfKind(CodeParameterKind.QueryParameter)) || // we're on an overload and the original method has no query parameters
+ !codeElement.IsOverload && queryStringParam == null) // we're on the original method and there is no query string parameter
+ skipIndex++;// we skip the query string parameter null value
+ requestInfoParameters.AddRange(paramsList.Where(x => x == null).Skip(skipIndex).Select(x => "null"));
+ var paramsCall = requestInfoParameters.Any() ? requestInfoParameters.Aggregate((x,y) => $"{x}, {y}") : string.Empty;
+ writer.WriteLine($"{prefix}{generatorMethodName}({paramsCall});");
+ }
+ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
- writer.WriteLine("final RequestInfo requestInfo = new RequestInfo() {{");
+ writer.WriteLine($"final RequestInfo {requestInfoVarName} = new RequestInfo() {{{{");
writer.IncreaseIndent();
writer.WriteLines($"uri = new URI({conventions.CurrentPathPropertyName} + {conventions.PathSegmentPropertyName});",
$"httpMethod = HttpMethod.{codeElement.HttpMethod?.ToString().ToUpperInvariant()};");
@@ -203,27 +214,34 @@ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter req
writer.WriteLine("}};");
if(requestBodyParam != null)
if(requestBodyParam.Type.Name.Equals(conventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
- writer.WriteLine($"requestInfo.setStreamContent({requestBodyParam.Name});");
+ writer.WriteLine($"{requestInfoVarName}.setStreamContent({requestBodyParam.Name});");
else
- writer.WriteLine($"requestInfo.setContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
+ writer.WriteLine($"{requestInfoVarName}.setContentFromParsable({requestBodyParam.Name}, {conventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
if(queryStringParam != null) {
var httpMethodPrefix = codeElement.HttpMethod.ToString().ToFirstCharacterUpperCase();
writer.WriteLine($"if ({queryStringParam.Name} != null) {{");
writer.IncreaseIndent();
writer.WriteLines($"final {httpMethodPrefix}QueryParameters qParams = new {httpMethodPrefix}QueryParameters();",
$"{queryStringParam.Name}.accept(qParams);",
- "qParams.AddQueryParameters(requestInfo.queryParameters);");
+ $"qParams.AddQueryParameters({requestInfoVarName}.queryParameters);");
writer.DecreaseIndent();
writer.WriteLine("}");
}
if(headersParam != null) {
writer.WriteLine($"if ({headersParam.Name} != null) {{");
writer.IncreaseIndent();
- writer.WriteLine($"{headersParam.Name}.accept(requestInfo.headers);");
+ writer.WriteLine($"{headersParam.Name}.accept({requestInfoVarName}.headers);");
+ writer.DecreaseIndent();
+ writer.WriteLine("}");
+ }
+ if(optionsParam != null) {
+ writer.WriteLine($"if ({optionsParam.Name} != null) {{");
+ writer.IncreaseIndent();
+ writer.WriteLine($"{requestInfoVarName}.addMiddlewareOptions({optionsParam.Name}.toArray(new MiddlewareOption[0]));");
writer.DecreaseIndent();
writer.WriteLine("}");
}
- writer.WriteLine("return requestInfo;");
+ writer.WriteLine($"return {requestInfoVarName};");
}
private void WriteSerializerBody(CodeClass parentClass, LanguageWriter writer) {
var additionalDataProperty = parentClass.GetPropertiesOfKind(CodePropertyKind.AdditionalData).FirstOrDefault();
diff --git a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
index 0e5e434c1b..775e8886be 100644
--- a/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
+++ b/src/Kiota.Builder/Writers/TypeScript/CodeMethodWriter.cs
@@ -30,6 +30,7 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
var requestBodyParam = codeElement.Parameters.OfKind(CodeParameterKind.RequestBody);
var queryStringParam = codeElement.Parameters.OfKind(CodeParameterKind.QueryParameter);
var headersParam = codeElement.Parameters.OfKind(CodeParameterKind.Headers);
+ var optionsParam = codeElement.Parameters.OfKind(CodeParameterKind.Options);
if(!codeElement.IsOfKind(CodeMethodKind.Setter))
foreach(var parameter in codeElement.Parameters.Where(x => !x.Optional).OrderBy(x => x.Name)) {
writer.WriteLine($"if(!{parameter.Name}) throw new Error(\"{parameter.Name} cannot be undefined\");");
@@ -47,10 +48,10 @@ public override void WriteCodeElement(CodeMethod codeElement, LanguageWriter wri
WriteSerializerBody(inherits, parentClass, writer);
break;
case CodeMethodKind.RequestGenerator:
- WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, writer);
+ WriteRequestGeneratorBody(codeElement, requestBodyParam, queryStringParam, headersParam, optionsParam, writer);
break;
case CodeMethodKind.RequestExecutor:
- WriteRequestExecutorBody(codeElement, requestBodyParam, queryStringParam, headersParam, isVoid, returnType, writer);
+ WriteRequestExecutorBody(codeElement, new List {requestBodyParam, queryStringParam, headersParam, optionsParam}, isVoid, returnType, writer);
break;
case CodeMethodKind.Getter:
WriteGetterBody(codeElement, writer, parentClass);
@@ -153,7 +154,7 @@ private void WriteDeserializerBody(CodeMethod codeElement, CodeClass parentClass
writer.DecreaseIndent();
writer.WriteLine("]);");
}
- private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, bool isVoid, string returnType, LanguageWriter writer) {
+ private void WriteRequestExecutorBody(CodeMethod codeElement, IEnumerable parameters, bool isVoid, string returnType, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
var generatorMethodName = (codeElement.Parent as CodeClass)
@@ -163,7 +164,7 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
?.Name
?.ToFirstCharacterLowerCase();
writer.WriteLine($"const requestInfo = this.{generatorMethodName}(");
- var requestInfoParameters = new List { requestBodyParam?.Name, queryStringParam?.Name, headersParam?.Name }.Where(x => x != null);
+ var requestInfoParameters = parameters.Select(x => x?.Name).Where(x => x != null);
if(requestInfoParameters.Any()) {
writer.IncreaseIndent();
writer.WriteLine(requestInfoParameters.Aggregate((x,y) => $"{x}, {y}"));
@@ -175,23 +176,26 @@ private void WriteRequestExecutorBody(CodeMethod codeElement, CodeParameter requ
var newFactoryParameter = GetTypeFactory(isVoid, isStream, returnType);
writer.WriteLine($"return this.httpCore?.{genericTypeForSendMethod}(requestInfo,{newFactoryParameter} responseHandler) ?? Promise.reject(new Error('http core is null'));");
}
- private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, LanguageWriter writer) {
+ private const string requestInfoVarName = "requestInfo";
+ private void WriteRequestGeneratorBody(CodeMethod codeElement, CodeParameter requestBodyParam, CodeParameter queryStringParam, CodeParameter headersParam, CodeParameter optionsParam, LanguageWriter writer) {
if(codeElement.HttpMethod == null) throw new InvalidOperationException("http method cannot be null");
- writer.WriteLines("const requestInfo = new RequestInfo();",
- $"requestInfo.URI = (this.{localConventions.CurrentPathPropertyName} ?? '') + this.{localConventions.PathSegmentPropertyName},",
- $"requestInfo.httpMethod = HttpMethod.{codeElement.HttpMethod.ToString().ToUpperInvariant()},");
+ writer.WriteLines($"const {requestInfoVarName} = new RequestInfo();",
+ $"{requestInfoVarName}.URI = (this.{localConventions.CurrentPathPropertyName} ?? '') + this.{localConventions.PathSegmentPropertyName},",
+ $"{requestInfoVarName}.httpMethod = HttpMethod.{codeElement.HttpMethod.ToString().ToUpperInvariant()},");
if(headersParam != null)
- writer.WriteLine($"{headersParam.Name} && requestInfo.setHeadersFromRawObject(h);");
+ writer.WriteLine($"{headersParam.Name} && {requestInfoVarName}.setHeadersFromRawObject(h);");
if(queryStringParam != null)
- writer.WriteLines($"{queryStringParam.Name} && requestInfo.setQueryStringParametersFromRawObject(q);");
+ writer.WriteLines($"{queryStringParam.Name} && {requestInfoVarName}.setQueryStringParametersFromRawObject(q);");
if(requestBodyParam != null) {
if(requestBodyParam.Type.Name.Equals(localConventions.StreamTypeName, StringComparison.OrdinalIgnoreCase))
- writer.WriteLine($"requestInfo.setStreamContent({requestBodyParam.Name});");
+ writer.WriteLine($"{requestInfoVarName}.setStreamContent({requestBodyParam.Name});");
else
- writer.WriteLine($"requestInfo.setContentFromParsable({requestBodyParam.Name}, this.{localConventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
+ writer.WriteLine($"{requestInfoVarName}.setContentFromParsable({requestBodyParam.Name}, this.{localConventions.HttpCorePropertyName}, \"{codeElement.ContentType}\");");
}
- writer.WriteLine("return requestInfo;");
+ if(optionsParam != null)
+ writer.WriteLine($"{optionsParam.Name} && {requestInfoVarName}.addMiddlewareOptions(...{optionsParam.Name});");
+ writer.WriteLine($"return {requestInfoVarName};");
}
private void WriteSerializerBody(bool inherits, CodeClass parentClass, LanguageWriter writer) {
var additionalDataProperty = parentClass.GetPropertiesOfKind(CodePropertyKind.AdditionalData).FirstOrDefault();
diff --git a/tests/Kiota.Builder.Tests/Refiners/JavaLanguageRefinerTests.cs b/tests/Kiota.Builder.Tests/Refiners/JavaLanguageRefinerTests.cs
index fd102aaede..05d68b8731 100644
--- a/tests/Kiota.Builder.Tests/Refiners/JavaLanguageRefinerTests.cs
+++ b/tests/Kiota.Builder.Tests/Refiners/JavaLanguageRefinerTests.cs
@@ -237,7 +237,7 @@ public void CorrectsCoreType() {
}).First();
serializationMethod.AddParameter(new CodeParameter(serializationMethod) {
Name = "handler",
- ParameterKind = CodeParameterKind.ResponseHandler,
+ ParameterKind = CodeParameterKind.Serializer,
Type = new CodeType(executorMethod) {
Name = serializerDefaultName,
}
@@ -252,6 +252,76 @@ public void CorrectsCoreType() {
Assert.Empty(model.GetChildElements(true).OfType().SelectMany(x => x.Parameters).Where(x => headersDefaultName.Equals(x.Type.Name)));
Assert.Empty(model.GetChildElements(true).OfType().SelectMany(x => x.Parameters).Where(x => serializerDefaultName.Equals(x.Type.Name)));
}
+ [Fact]
+ public void AddsMethodsOverloads() {
+ var builder = root.AddClass(new CodeClass (root) {
+ Name = "model",
+ ClassKind = CodeClassKind.RequestBuilder
+ }).First();
+ var executor = builder.AddMethod(new CodeMethod(builder) {
+ Name = "executor",
+ MethodKind = CodeMethodKind.RequestExecutor,
+ ReturnType = new CodeType(builder) {
+ Name = "string"
+ }
+ }).First();
+ executor.Parameters.Add(new CodeParameter(executor) {
+ Name = "handler",
+ ParameterKind = CodeParameterKind.ResponseHandler,
+ Type = new CodeType(executor) {
+ Name = "string"
+ }
+ });
+ executor.AddParameter(new CodeParameter(executor) {
+ Name = "headers",
+ ParameterKind = CodeParameterKind.Headers,
+ Type = new CodeType(executor) {
+ Name = "string"
+ }
+ });
+ executor.AddParameter(new CodeParameter(executor) {
+ Name = "query",
+ ParameterKind = CodeParameterKind.QueryParameter,
+ Type = new CodeType(executor) {
+ Name = "string"
+ }
+ });
+ executor.AddParameter(new CodeParameter(executor) {
+ Name = "body",
+ ParameterKind = CodeParameterKind.RequestBody,
+ Type = new CodeType(executor) {
+ Name = "string"
+ }
+ });
+ executor.AddParameter(new CodeParameter(executor) {
+ Name = "options",
+ ParameterKind = CodeParameterKind.Options,
+ Type = new CodeType(executor) {
+ Name = "string"
+ }
+ });
+ var generator = builder.AddMethod(new CodeMethod(builder) {
+ Name = "generator",
+ MethodKind = CodeMethodKind.RequestGenerator,
+ ReturnType = new CodeType(builder) {
+ Name = "string"
+ }
+ }).First();
+ generator.Parameters.AddRange(executor.Parameters.Where(x => !x.IsOfKind(CodeParameterKind.ResponseHandler)));
+ ILanguageRefiner.Refine(new GenerationConfiguration { Language = GenerationLanguage.Java }, root);
+ var childMethods = builder.GetChildElements(true).OfType();
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestExecutor) && x.Parameters.Count == 1));//only the body
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestGenerator) && x.Parameters.Count == 1));//only the body
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestExecutor) && x.Parameters.Count == 2));// body + query params
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestGenerator) && x.Parameters.Count == 2));// body + query params
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestExecutor) && x.Parameters.Count == 3));// body + query params + headers
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestGenerator) && x.Parameters.Count == 3));// body + query params + headers
+ Assert.True(childMethods.Any(x => x.IsOverload && x.IsOfKind(CodeMethodKind.RequestExecutor) && x.Parameters.Count == 4));// body + query params + headers + options
+ Assert.True(childMethods.Any(x => !x.IsOverload && x.IsOfKind(CodeMethodKind.RequestGenerator) && x.Parameters.Count == 4));// body + query params + headers + options
+ Assert.True(childMethods.Any(x => !x.IsOverload && x.IsOfKind(CodeMethodKind.RequestExecutor) && x.Parameters.Count == 5));// body + query params + headers + options + response handler
+ Assert.Equal(9, childMethods.Count());
+ Assert.Equal(7, childMethods.Count(x => x.IsOverload));
+ }
#endregion
}
}
diff --git a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs
index a45375466a..260fdacec5 100644
--- a/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs
+++ b/tests/Kiota.Builder.Tests/Refiners/TypeScriptLanguageRefinerTests.cs
@@ -137,7 +137,7 @@ public void CorrectsCoreType() {
}).First();
serializationMethod.AddParameter(new CodeParameter(serializationMethod) {
Name = "handler",
- ParameterKind = CodeParameterKind.ResponseHandler,
+ ParameterKind = CodeParameterKind.Serializer,
Type = new CodeType(executorMethod) {
Name = serializerDefaultName,
}
diff --git a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
index 12bd4eea42..c93aea9ea9 100644
--- a/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/CSharp/CodeMethodWriterTests.cs
@@ -110,6 +110,11 @@ private void AddRequestBodyParameters() {
ParameterKind = CodeParameterKind.ResponseHandler,
Type = stringType,
});
+ method.AddParameter(new CodeParameter(method) {
+ Name = "o",
+ ParameterKind = CodeParameterKind.Options,
+ Type = stringType,
+ });
}
[Fact]
public void WritesRequestBodiesThrowOnNullHttpMethod() {
@@ -143,6 +148,7 @@ public void WritesRequestGeneratorBody() {
Assert.Contains("h?.Invoke", result);
Assert.Contains("AddQueryParameters", result);
Assert.Contains("SetContentFromParsable", result);
+ Assert.Contains("AddMiddlewareOptions", result);
Assert.Contains("return requestInfo;", result);
AssertExtensions.CurlyBracesAreClosed(result);
}
@@ -370,5 +376,15 @@ public void WritesApiConstructorWithBackingStore() {
var result = tw.ToString();
Assert.Contains("EnableBackingStore", result);
}
+ [Fact]
+ public void ThrowsOnGetter() {
+ method.MethodKind = CodeMethodKind.Getter;
+ Assert.Throws(() => writer.Write(method));
+ }
+ [Fact]
+ public void ThrowsOnSetter() {
+ method.MethodKind = CodeMethodKind.Setter;
+ Assert.Throws(() => writer.Write(method));
+ }
}
}
diff --git a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
index 60ef07e4a8..8e2ebf6d15 100644
--- a/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/Java/CodeMethodWriterTests.cs
@@ -110,6 +110,11 @@ private void AddRequestBodyParameters() {
ParameterKind = CodeParameterKind.ResponseHandler,
Type = stringType,
});
+ method.AddParameter(new CodeParameter(method) {
+ Name = "o",
+ ParameterKind = CodeParameterKind.Options,
+ Type = stringType,
+ });
}
[Fact]
public void WritesNullableVoidTypeForExecutor(){
@@ -154,10 +159,29 @@ public void WritesRequestGeneratorBody() {
Assert.Contains("h.accept(requestInfo.headers)", result);
Assert.Contains("AddQueryParameters", result);
Assert.Contains("setContentFromParsable", result);
+ Assert.Contains("addMiddlewareOptions", result);
Assert.Contains("return requestInfo;", result);
AssertExtensions.CurlyBracesAreClosed(result);
}
[Fact]
+ public void WritesRequestGeneratorOverloadBody() {
+ method.MethodKind = CodeMethodKind.RequestGenerator;
+ method.HttpMethod = HttpMethod.Get;
+ method.OriginalMethod = method;
+ AddRequestBodyParameters();
+ writer.Write(method);
+ var result = tw.ToString();
+ Assert.DoesNotContain("final RequestInfo requestInfo = new RequestInfo()", result);
+ Assert.DoesNotContain("httpMethod = HttpMethod.GET", result);
+ Assert.DoesNotContain("h.accept(requestInfo.headers)", result);
+ Assert.DoesNotContain("AddQueryParameters", result);
+ Assert.DoesNotContain("setContentFromParsable", result);
+ Assert.DoesNotContain("addMiddlewareOptions", result);
+ Assert.DoesNotContain("return requestInfo;", result);
+ Assert.Contains("return methodName(b, q, h, o)", result);
+ AssertExtensions.CurlyBracesAreClosed(result);
+ }
+ [Fact]
public void WritesInheritedDeSerializerBody() {
method.MethodKind = CodeMethodKind.Deserializer;
method.IsAsync = false;
diff --git a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
index 77e5a3e6dd..f127cf3be8 100644
--- a/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
+++ b/tests/Kiota.Builder.Tests/Writers/TypeScript/CodeMethodWriterTests.cs
@@ -110,6 +110,11 @@ private void AddRequestBodyParameters() {
ParameterKind = CodeParameterKind.ResponseHandler,
Type = stringType,
});
+ method.AddParameter(new CodeParameter(method) {
+ Name = "o",
+ ParameterKind = CodeParameterKind.Options,
+ Type = stringType,
+ });
}
[Fact]
public void WritesRequestBodiesThrowOnNullHttpMethod() {
@@ -142,6 +147,7 @@ public void WritesRequestGeneratorBody() {
Assert.Contains("setHeadersFromRawObject", result);
Assert.Contains("setQueryStringParametersFromRawObject", result);
Assert.Contains("setContentFromParsable", result);
+ Assert.Contains("addMiddlewareOptions", result);
Assert.Contains("return requestInfo;", result);
AssertExtensions.CurlyBracesAreClosed(result);
}