apigee-127 / swagger-tools

A Node.js and browser module that provides tooling around Swagger.
MIT License
701 stars 373 forks source link

Content-Disposition header is ignored #583

Closed sauravpandit closed 6 years ago

sauravpandit commented 6 years ago

Hi, I was trying to develop an API on top of weather example. I was try create an api which will let user download excel sheet. I have added following api path in existing swagger.json

"/reportweather":{
      "get":{
        "x-swagger-router-controller": "Weather",
        "operationId": "getWeatherReport",
        "tags": ["/weather"],
        "produces":["application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
        "responses":{
          "200":{
              "description":"Response for success message",
              "schema":{
                  "type":"string",
                  "format":"binary"
              }
          },
          "default":{
              "description":"Every response except success",
              "schema":{
                  "type":"string"
              }
          }
        }
      }
    }

I have added the following code in Weather.js file

module.exports.getWeatherReport = function getWeatherReport (req, res, next){
  var options = {
    root: __dirname,
    dotfiles: 'deny',
    headers: {
        'x-timestamp': Date.now(),
        'x-sent': true,
        'Content-Disposition':'attachment; filename="Book.xlsx"'
    }
  };

  var fileName = 'Book.xlsx';

  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
      console.log('Sent:-----');
    }
  });
} 

Now when I am trying to access the api using Swagger UI built in withing application, instead of file I am getting some binary data. Most surprisingly I am not seeing the header which I have set in Node js code.

{
  "date": "Sun, 05 Aug 2018 18:17:48 GMT",
  "etag": "W/\"2075-16475d6a2b0\"",
  "last-modified": "Sat, 07 Jul 2018 17:42:38 GMT",
  "x-powered-by": "Express",
  "content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "x-sent": "true",
  "x-timestamp": "1533493068295",
  "cache-control": "public, max-age=0",
  "accept-ranges": "bytes",
  "content-length": "8309"
} 

If I hit the url directly (http://localhost:3000/api/reportweather) from browser the file is getting downloaded but it is taking the name from url without any extension(Just reportweather). It is not downloading the file as set using "Content-Disposition".

If I create a plain express project and use the code

var options = {
    root: __dirname,
    dotfiles: 'deny',
    headers: {
        'x-timestamp': Date.now(),
        'x-sent': true,
        'Content-Disposition':'attachment; filename="Book.xlsx"'
    }
  };

  var fileName = 'Book.xlsx';

  res.sendFile(fileName, options, function (err) {
    if (err) {
      next(err);
    } else {
      console.log('Sent:', fileName);
      console.log('Sent:-----');
    }
  });

The file is getting download as expected. It is following the instruction given in 'Content-Disposition' header. 'Content-Disposition':'attachment; filename="Book.xlsx"' I am not understanding why this header is getting deleted from response. It will great if anyone help me on this.

sauravpandit commented 6 years ago

I know this tool use swagger ui which is not giving option for file downloading but why when hitting directly from browser is not downloading the file withe name type set in header but running same code from plain express project is working as expected.

sauravpandit commented 6 years ago

@whitlockjc Can you help me on this?

whitlockjc commented 6 years ago

swagger-tools doesn't remove headers, it might validate a response and throw a 500 but that isn't what's happening. How are you testing this? There is a known issue in swagger-ui where file downloads don't work.

sauravpandit commented 6 years ago

@whitlockjc Sorry for replying late. I am trying it in two way. First I am accessing it using swagger UI which is integrated with swagger tool and second way is hitting the URL directly in browser. I will focus here on the second way. I am hitting the API URL directly from browser(Chrome, Edge) http://localhost:3000/api/reportweather In context disposition I have set 'Content-Disposition':'attachment; filename="Book.xlsx"' Which means it should prompt me to save "Book.xlsx" file but in reality it is downloading a binary response without any extension or file type. I know there is a know issue with swagger UI but I am accessing API using browser. I have run swagger tool in debug mood using VScode. I also have not seen anywhere it is removing any header but I am also not understanding why this issue is happening. Thank you for replying back.

whitlockjc commented 6 years ago

Hit the API directly from the CLI and see what happens. Do so in verbose mode so I can see the headers sent back.

sauravpandit commented 6 years ago

I have found solution. I have cleared browser cache and tried again. I am getting proper response. @whitlockjc Thank you for providing quick response.