0

I want to add an API common prefix for all controllers, e.g. /api/v1. I am using inversify with the @inversify/http-express package.

Here is my current base server adapter setup:

class Server {
  private adapter: InversifyExpressHttpAdapter;

  constructor(private readonly container: Container) {
    this.adapter = new InversifyExpressHttpAdapter(this.container, {
      useCookies: true,
      useJson: true,
    });

    this.adapter.applyGlobalMiddleware(CorsMiddleware);
    this.adapter.applyGlobalMiddleware(HelmetMiddleware);
    this.adapter.applyGlobalMiddleware(RateLimitMiddleware);
    this.adapter.applyGlobalMiddleware(CookieParserMiddleware);
    this.adapter.applyGlobalMiddleware(LoggerMiddleware);

    const swaggerProvider: SwaggerUiProvider = new SwaggerUiProvider({
      api: {
        openApiObject: {
          info: {
            title: "My Backend",
            version: pkg.version,
          },
          openapi: "3.1.1",
        },
        path: "/docs",
      },
      ui: {
        title: "My backend API docs",
      },
    });

    swaggerProvider.provide(this.container);

    this.adapter.useGlobalFilters(GlobalErrorFilter);
  }

  public async getApp() {
    const app = await this.adapter.build();

    app.use(notFoundMiddleware);

    return app;
  }
}

Here I'm using InversifyExpressHttpAdapter class. Now, how can I add api common prefix?

New contributor
Saiful Islam is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

1 Answer 1

0

The Controller decorator can be a good base to create a prefixed controller:

import { Controller } from '@inversifyjs/http-core';
import { BindingScope, ServiceIdentifier } from 'inversify';

interface ControllerOptions {
  path?: string;
  priority?: number;
  scope?: BindingScope;
  serviceIdentifier?: ServiceIdentifier;
}


export function PrefixedController(
  prefix: string,
): (pathOrOptions?: string | ControllerOptions) => ClassDecorator {
  return (pathOrOptions?: string | ControllerOptions): ClassDecorator => {
    if (pathOrOptions === undefined) {
      return Controller(prefix);
    }
    if (typeof pathOrOptions === 'string') {
      // URL paths are normalized, so we are safe to concatenate them like this
      return Controller(`${prefix}/${pathOrOptions}`);
    }

    const optionsWithPrefixedPath: ControllerOptions = {
      ...pathOrOptions,
      // URL paths are normalized, so we are safe to concatenate them like this
      path: `${prefix}/${pathOrOptions.path ?? ''}`,
    };

    return Controller(optionsWithPrefixedPath);
  };
}

export const ApiV1Controller: (
  pathOrOptions?: string | ControllerOptions,
) => ClassDecorator = PrefixedController('/api/v1');

This allows you to define controllers for your versioned endpoints:

@ApiV1Controller('/users')
@OasSummary('User management routes')
export class UserController {
  // Your controller implementation here :)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.