Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for multiple servers information #720

Open
2 of 4 tasks
deividfortuna opened this issue Jun 3, 2020 · 10 comments
Open
2 of 4 tasks

Support for multiple servers information #720

deividfortuna opened this issue Jun 3, 2020 · 10 comments

Comments

@deividfortuna
Copy link

Sorting

  • I'm submitting a ...

    • bug report
    • feature request
    • support request
  • I confirm that I

    • used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

servers:
  - url: https://api.example.com/v1
    description: Production server (uses live data)
  - url: https://sandbox-api.example.com:8443/v1
    description: Sandbox server (uses test data)

Current Behavior

servers:
  - url: https://api.example.com/v1 

Possible Solution

  private buildServers() {
    if (Array.isArray(this.config.host)) {
      return this.config.host.map(host => this.buildServer(host));
    } else {
      return [this.buildServer({ host: this.config.host })];
    }
  }

  private buildServer(serverConfig: { host?: string; description?: string }): Swagger.Server {
    const basePath = normalisePath(this.config.basePath as string, '/', undefined, false);
    const scheme = this.config.schemes ? this.config.schemes[0] : 'https';
    const url = serverConfig.host ? `${scheme}://${serverConfig.host}${basePath}` : basePath;

    const server = {
      url,
    } as Swagger.Server;

    if (serverConfig.description) {
      server.description = serverConfig.description;
    }

    return server;
  }

Context (Environment)

Version of the library: 3.0.8
Version of NodeJS: v12.16.3

  • Confirm you were using yarn not npm: [x]

Detailed Description

OpenApi3 supports multiples servers information and that can be useful to be used swagger pointing to multiple environments.

Breaking change?

The solution is a workaround to a breaking change.

@WoH
Copy link
Collaborator

WoH commented Jun 3, 2020

There is an abandoned PR here.
As I said in the review, we should support host (for backwards compat), but allow OpenAPI 3 to define a servers?: OpenAPIServer[] config setting.

@WoH WoH added the help wanted label Jun 3, 2020
@deividfortuna
Copy link
Author

Thanks for reply @WoH, I'm keen to move the PR # #633 forward if it is the case. My solution also support host configuration as a string but if it is an array will treat as multiples host configuration. I do have the changes on my machine not sure if I should open another PR, it is lacking corner cases coverage at this moment.

export interface Spec2 extends Spec {
    swagger: '2.0';
    host?: string | Array<Host>;
...
  export interface Host {
    host: string;
    description?: string;
  }

@WoH
Copy link
Collaborator

WoH commented Jun 3, 2020

What would you do in case specVersion: 2 and hosts is an Array?
Warn and take the first one's host?
My worry here is that both formats are very different (host: string vs. servers: {url: string, description: string}[] and I don't know if I'd want to handle all that translation.

@deividfortuna
Copy link
Author

deividfortuna commented Jun 3, 2020

Thanks @WoH, it make sense. I'll take a look in the #633 and see what I can do to help move forward.

@github-actions github-actions bot added the Stale label Jan 8, 2021
Repository owner deleted a comment from github-actions bot Jan 8, 2021
@WoH WoH added enhancement and removed Stale labels Jan 8, 2021
@DroidGar
Copy link

its any workaround in mid time?

@Dynasty9
Copy link

Dynasty9 commented Mar 11, 2021

Workaround: Below I used the spec.spec override to get my servers in there.

// tsoa.json
	"spec": {
		"specVersion": 3,
		"basePath": "/api/v1",
		"spec": { // Override the servers section
			"servers": [
				{
					"url": "http://localhost:8080/api/v1",
					"description": "Local development"
				},
				{
					"url": "http://prod:8080/api/v1",
					"description": "Prod development"
				}
			]
		},
	},

Resulting in the final

// swagger.json
  {
   ... 
  "servers": [
    {
      "url": "http://localhost:8080/api/v1",
      "description": "Local development"
    },
    {
      "url": "http://prod:8080/api/v1",
      "description": "Prod development"
    }
  ]```

@karlismelderis
Copy link

also let's open option to specify http/https
if server is localhost I don't think anyone expects to run under SSL

@guhyeon
Copy link

guhyeon commented May 30, 2023

Hmm...
This is a bit off topic, how did you do api versioning with tsoa?

@Vince-Smith
Copy link

Hmm... This is a bit off topic, how did you do api versioning with tsoa?

Also curious about this as I'm currently evaluating tsoa as an option for a project that uses custom headers for versioning.

It seems like templates might be a solution, but I'm just starting to dig into that.

@1muen
Copy link

1muen commented Dec 19, 2024

I am also curious how others do api versioning. Currently we have something like this:

import { v1 } from "./v1.js";

@Tags("V2")
@Route("/api/v2/something")
@Response<string>("500", "Internal server error")
export class v2 extends v1 {
    /**
    * something
    */
    // @Example<...
    @Post("/create")
    public async create(
        @Res() serverErrorResponse: TsoaResponse<500, ErrorApiResponse>,
    ): Promise<SuccessfulApiResponse<null>> {
        logger.debug("v2::create");

        return await super.create(

Hoped that tsoa would pick up the routes it inherits from v1 but unfortunately its not the case right now. So a lot annotation is duplicated and the super.method is called.

But back on topic:
Multiple servers are supported: #1682

But as was pointed out earlier, I also have the problem of specifying localhost, int and prod:

also let's open option to specify http/https if server is localhost I don't think anyone expects to run under SSL

Maybe it could be fixed by something like this:

diff --git a/packages/cli/src/swagger/specGenerator3.ts b/packages/cli/src/swagger/specGenerator3.ts
index 1510cc76..239e32d9 100644
--- a/packages/cli/src/swagger/specGenerator3.ts
+++ b/packages/cli/src/swagger/specGenerator3.ts
@@ -144,7 +144,7 @@ export class SpecGenerator3 extends SpecGenerator {
     const basePath = normalisePath(this.config.basePath as string, '/', undefined, false);
     const scheme = this.config.schemes ? this.config.schemes[0] : 'https';
     const hosts = this.config.servers ? this.config.servers : this.config.host ? [this.config.host!] : undefined;
-    const convertHost = (host: string) => ({ url: `${scheme}://${host}${basePath}` });
+    const convertHost = (host: string) => host.includes("://") ? { url: host + basePath } : ({ url: `${scheme}://${host}${basePath}` });
     return (hosts?.map(convertHost) || [{ url: basePath }]) as Swagger.Server[];
   }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants