Skip to content

mediaclip/http-pipeline-ts

Repository files navigation

HTTP Pipeline

This library provides a way to write clean and reliable HTTP Clients, instead of writing complex fetch(). It uses the same principle as those available in the HttpPipeline of the Azure.Core from the .NET Azure SDK. More details are explained in this video

Simple request

Simple example, using the HttpMessageBuilder to build the request easily, then send it through the pipeline, and then parse the response and throw if the server responded with an error.

Example

type Response = {
    id: number;
    // ...
}

class MyAwesomeClient {
    constructor(
        private readonly httpPipeline: HttpPipeline,
        private readonly httpMessageResponseUtil: IHttpMessageResponseUtil,
    ) {
    }

    async createSomething(): Promise<Response> {
        const message = new HttpMessageBuilder()
            .withMethod('POST')
            .withUrl('/api/blogs')
            .withQueryString('test', 'true')
            .withHeader('Authorization', 'Bearer some-auth-token')
            .withJsonBody({
                title: 'some-title',
                content: 'some-content'
            })
            .build();

        await pipeline.send(message);
        return httpMessageResponseUtil.parseJsonResponse<Response>(message);
    }
}

let options = new HttpPipelineOptions(); // Configure policies, retry etc...
const pipeline = new HttpPipelineFactory().build(options);
var client = new MyAwesomeClient(pipeline, new HttpMessageResponseUtil());

Policies

Policies are like middleware in ASP.NET Core or Interceptors in Angular. They allow execution of code before/after each request

Illustration of the pipeline

You can register a policy to be called once per request, or once per retry.

For example, this allows you to add a custom header or handle all common errors from the server at one place.

Example

class AuthenticationHttpPipelinePolicy extends HttpPipelinePolicy {
    static propertyKey: symbol = Symbol();

    async process(message: HttpMessage, pipeline: HttpPipelinePolicy[]): Promise<void> {
        let authentication = message.properties[AuthenticationHttpPipelinePolicy.propertyKey] as Authentication;
        if (authentication) {
            switch (authentication.type) {
                case 'JWT':
                    message.request.headers['Authorization'] = 'Bearer ' + authentication.token;
                    break;
                case 'ApiKey':
                    message.request.headers['Authorization'] = authentication.apiKey;
                    break;
                // .... Other complex scenario, like request that need to be signed, with timestamp etc...
            }
        }
        await this.processNext(message, pipeline);
    }
}

Then you need to register a policy like this:

let options = new HttpPipelineOptions();
options.perRetryPolicies.push(new AuthenticationHttpPipelinePolicy());
const pipeline = new HttpPipelineFactory().build(options);

And then you can configure the authentication to use like this:

const message = new HttpMessageBuilder()
    .withUrl('/api/posts')
    .withProperty<Authentication>(AuthenticationHttpPipelinePolicy.propertyKey, {type: 'JWT', token: 'some-token'})
    .build();
const message = new HttpMessageBuilder()
    .withUrl('/api/posts')
    .withProperty<Authentication>(AuthenticationHttpPipelinePolicy.propertyKey, {type: 'ApiKey', apiKey: 'some-api-key'})
    .build();

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published