2

I want to create an endpoint that sends back the content of a file using sendFile. Writing the route on my own in my Express application, I know what to do and it works:

   app.get('/api/logs', (req, res) => { 
      var path = require('path'); 
      res.sendFile(path.join(__dirname, '../../../..', 'file.log')); 
    });

But since I am using tsoa, I need to write these in my controller which I would do like this:

@Route('getlogs')
export class LoggerController extends Controller {
  @Get()
  async getLogs(@Response("") res: express.Response) {
    let filePath = path.join(__dirname, '../../../..', 'file.log');
    res.sendFile(filePath);
    return res;
  }
}

but doing so, I am running in the following error:

 Generate routes error.
 Error: Multiple matching models found for referenced type Response; please make model names unique. 

This is true. I have a model for Response in node_modules/aws-sdk and in node_modules/@types. So I imagine maybe I should not use express.Response in this setup. It should not be that hard to do this.

If someone has an idea how to handle this, I would be very glad.

user
  • 117
  • 9

2 Answers2

0

I think your error rather originates from the @Response() Decorator that you are using, than from the express.Response object.

Looking at the tsoa documentation for responses shows the following:

Only tsoa >= 3.1

In recent versions of tsoa, we have the option to inject a framework-agnostic responder function into our function that we can call to formulate a response that does not comply with the return type of our controller method/status code and headers (which is used for the success response). This is especially useful to reply with an error response without the risk of type mismatches associated with throwing errors. In order to inject one/more responders, we can use the @Res() decorator

import { Route, Controller, Get, Query, Res, TsoaResponse } from 'tsoa'

@Route('/greeting')
export class GreetingsController extends Controller {
  /**
   * @param notFoundResponse The responder function for a not found response
   */
  @Get('/')
  public async greet(@Query() name?: string, @Res() notFoundResponse: TsoaResponse<404, { reason: string }>): Promise<string> {
    if (!name) {
      notFoundResponse(404, { reason: "We don't know you yet. Please provide a name" });
    }

    return `Hello, ${name}`;
  }

Did not test it so far, but should work for your scenario, too.

SPMSE
  • 478
  • 3
  • 14
0

use response.req

I came across same issue using multer to handle handle file upload and as I can't use it as express milddleware, I had to use it in my controller and request object is require ( although for completeness sake by TypeScript I guess ) and I passed request.res in place of request and Typescript accepted it and my middle ware worked perfectly.

import { Request, Route, Get, Controller } from 'tsoa';
import express from 'express';
@Route('getlogs')
export class LoggerController extends Controller {
  @Get()
  async getLogs(@Request("") request: express.Request) {
    let filePath = path.join(__dirname, '../../../..', 'file.log');
    let res = request.res; // not request.response but exactly .res
    res.sendFile(filePath);
    return res;
  }
}

I have not used this to send back response though. from the doc, there are some cases where this object in the request method will be undefined.

I just used this request.res to send data back to the client just like normal express response and it worked successfully

R A Omeiza
  • 11
  • 4