Closed ffMathy closed 3 years ago
Thanks for sharing the feedback @ffMathy @joheredi Does our current work to move to the new Azure Core help with this or this would be more solvable via the low level client project?
@ramya-rao-a thank you for your reply.
Not sure actually. Would it be possible to show some kind of example of how to do this with the new Azure Core?
Is there any documentation on the new way of doing things?
@sarangan12 Can you share pointers with @ffMathy as to how to use our latest SDK code generator that is still in preview?
@ffMathy Meanwhile you can refer to https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/core/README.md and https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/core/core-rest-pipeline/documentation/core2.md for information around the current and new Azure Core packages
Yeah I've actually seen that guide, but I don't think it lives up to the rest of the documentation Microsoft provides in general.
It needs more examples for different use cases etc. It's very limited, and I can't see where it says how to add Middleware.
Fair
I was focusing on the fact that moving to the new Azure Core libraries would remove the dependency on node-fetch and did not pay attention to rest of the issues like "node-based language but still doesn't support node's http library"
In swaggergen (which I would like to switch away from), it is possible to define an "adapter". A simple abstraction that (per default) wraps the CoreHttp client, but can be substituted out (dependency inversion principle, open/closed principle).
Can you elaborate on this please?
Yeah sure: https://en.m.wikipedia.org/wiki/Adapter_pattern
In Swaggergen you can define an adapter to "tell" Swagger how to make requests. Essentially just an interface you can implement with a sendRequest
method, which you can then override and pass an instance of that implementation in via the constructor to the client.
@ffMathy we now allow setting your own http client in the client options when instantiating a generated client.
Here's a sample of using a custom HttpClient and also pipeline policies as Middleware, hope this is helpful.
Note: AdditionalPropertiesClient
is my generated package with the latest version of @autorest/typescript@beta
import {
createHttpHeaders,
HttpClient,
} from "@azure/core-rest-pipeline";
import { AdditionalPropertiesClient } from ".";
async function main() {
// Define a custom client to send the requests
// In this example we just log the request and
// send back a dummy response, but this could be
// plugged into any implementation
const customClient: HttpClient = {
sendRequest: async request => {
console.log(`Sending a ${request.method} request to ${request.url}`);
return {
headers: createHttpHeaders(),
bodyAsText: `{"foo": "bar"}`,
status: 200,
request
};
}
};
// Pass the custom HttpClient to the generated client
const client = new AdditionalPropertiesClient({
httpClient: customClient
});
// You can also use pipelines as middleware
client.pipeline.addPolicy({
name: "customPolicy",
sendRequest: async (request, next) => {
// You can manipulate the request before handing it off to the pipeline and eventually
// get sent.
request.headers.set("test-header", "hello world!");
// Handing it off to the pipeline to process all remaining policies and eventually
// reach the sendRequest on the HttpClient that we defined above (or the default if no custom HttpClient is provided)
const response = await next(request);
// You can also manipulate the response before handing it back to the pipeline and eventually reaching your client's method
const parsedBody = JSON.parse(response.bodyAsText ?? "{}");
parsedBody.testValue = "Added this is a pipeline policy!";
response.bodyAsText = JSON.stringify(parsedBody);
// And off the response to the pipeline
return response;
}
});
const result = await client.pets.createAPInProperties({ id: 1, name: "Foo" });
console.log(result);
// Output:
// Sending a PUT request to http://localhost:3000/additionalProperties/in/properties
// { foo: 'bar' }
}
main();
@joheredi this is fantastic - any chance it can make it to the documentation, so future users can also understand it?
Right now, the TypeScript generated code uses CoreHttp, which in turn seems to use either
XmlHttpRequest
ornode-fetch
, depending on what is available.However, since I am using Appcelerator Titanium to build my app (which is a node-based language but still doesn't support node's
http
library and therefore doesn't supportnode-fetch
either), I am out of options to make the generated code work for my app.In swaggergen (which I would like to switch away from), it is possible to define an "adapter". A simple abstraction that (per default) wraps the CoreHttp client, but can be substituted out (dependency inversion principle, open/closed principle).
I think it would be easy to implement in Autorest, and it would allow the library to be used anywhere, while retaining backwards compatibility.