librelist archives

« back to archive

attachment filename & wget & X-Accel-Redirect

attachment filename & wget & X-Accel-Redirect

From:
Demitri Muna
Date:
2012-09-21 @ 18:12
Hi,

I have a Flask app where some of my responses are returning static files. 
I determine the local path relative to a base directory, and then do this:

url = "/static/path/to/file"

response = make_response()
response.headers['Cache-Control'] = 'public'
response.headers['Content-Type'] = 'application/fits'
response.headers['Content-Disposition'] = 'attachment; filename=' + filename
response.headers['X-Accel-Redirect'] = url
return response

In my nginx configuration file, I have this:

location /static {
    internal;
    root /path/to/files;
}

This all works perfectly. The problem is that when using something like 
wget, the resulting filename is the URL used to fetch it, not the proper 
filename. Here's an example URL:

http://api.sdss3.org/spectrum?id=sdss.731.52460.423.26

When I do this:

% wget "http://api.sdss3.org/spectrum?id=sdss.731.52460.423.26"

the resulting filename is "spectrum?id=sdss.731.52460.423.26" instead of 
"spec-0731-52460-0423.fits". (Incidentally, I get the correct filename 
from the browser.)

Is the problem here Flask or nginx? Am I missing something? I can get it 
to work with

% wget --content-disposition ...

or to add "content_disposition = on" to a .wgetrc file, but I have a lot 
of users and would like to fix this at the source.

Cheers,
Demitri


Re: [flask] attachment filename & wget & X-Accel-Redirect

From:
Steven Kryskalla
Date:
2012-09-21 @ 18:16
On Fri, Sep 21, 2012 at 11:12 AM, Demitri Muna
<thatsanicehatyouhave@me.com> wrote:
> Is the problem here Flask or nginx? Am I missing something? I can get it
to work with
>

What happens when flask serves up the file without nginx? Do you get
the right behavior? That would tell you if the problem is flask or
nginx.

Also, the most useful bit of information to debug would be the headers
from nginx's response.

Re: [flask] attachment filename & wget & X-Accel-Redirect

From:
Demitri Muna
Date:
2012-09-21 @ 18:57
Hi.

On Sep 21, 2012, at 2:16 PM, Steven Kryskalla <skryskalla@gmail.com> wrote:

> What happens when flask serves up the file without nginx? Do you get
> the right behavior? That would tell you if the problem is flask or
> nginx.

Because the Flask app sends redirects the response as a partial file path 
via X-Accel-Redirect, it doesn't return the file in debug mode (i.e. 
without nginx). Well, it returns a file, but it's of zero length and has 
the same filename behavior.

I changed Flask in debug mode to return the file with the full path on disk:

return send_file("/path/to/file/from/root")

and this

wget "http://localhost:5555/spectrum?plate=276&fiber=627&mjd=51909"

returns a file with the (incorrect) name: 
"spectrum?plate=276&fiber=627&mjd=51909".

Or did you mean to run the app with Apache?

> Also, the most useful bit of information to debug would be the headers
> from nginx's response.

Pasted below.

Cheers,
Demitri

---

% wget -S "http://api.sdss3.org/spectrum?plate=276&fiber=627&mjd=51909"
--2012-09-21 14:47:28--  
http://api.sdss3.org/spectrum?plate=276&fiber=627&mjd=51909
Resolving api.sdss3.org... 128.122.53.67
Connecting to api.sdss3.org|128.122.53.67|:80... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 200 OK
  Server: nginx/1.0.15
  Date: Fri, 21 Sep 2012 18:45:39 GMT
  Content-Type: application/fits
  Content-Length: 892800
  Last-Modified: Wed, 02 May 2012 20:06:31 GMT
  Connection: keep-alive
  Cache-Control: public
  Content-Disposition: attachment; filename=spec-0276-51909-0627.fits
  Accept-Ranges: bytes
Length: 892800 (872K) [application/fits]
Saving to: `spectrum?plate=276&fiber=627&mjd=51909'

100%[========================================================>] 892,800
--.-K/s   in 0.008s  

2012-09-21 14:47:28 (102 MB/s) - `spectrum?plate=276&fiber=627&mjd=51909' 
saved [892800/892800]



This is the trace from Flask in debug more using "send_file":

% wget -S "http://localhost:5555/spectrum?plate=276&fiber=627&mjd=51909"
--2012-09-21 14:55:52--  
http://localhost:5555/spectrum?plate=276&fiber=627&mjd=51909
Resolving localhost... 127.0.0.1, ::1, fe80::1
Connecting to localhost|127.0.0.1|:5555... connected.
HTTP request sent, awaiting response... 
  HTTP/1.0 200 OK
  Content-Type: application/fits
  Last-Modified: Wed, 02 May 2012 20:06:31 GMT
  Cache-Control: public, max-age=43200
  Expires: Sat, 22 Sep 2012 06:54:18 GMT
  ETag: "flask-1335989191.0-892800-753999631"
  Connection: close
  Server: Werkzeug/0.8.3 Python/2.7.2+
  Date: Fri, 21 Sep 2012 18:54:18 GMT
Length: unspecified [application/fits]
Saving to: `spectrum?plate=276&fiber=627&mjd=51909.2'



Re: [flask] attachment filename & wget & X-Accel-Redirect

From:
Audrius Kažukauskas
Date:
2012-09-21 @ 18:39
On Fri, 2012-09-21 at 14:12:49 -0400, Demitri Muna wrote:
> When I do this:
> 
> % wget "http://api.sdss3.org/spectrum?id=sdss.731.52460.423.26"
> 
> the resulting filename is "spectrum?id=sdss.731.52460.423.26" instead
> of "spec-0731-52460-0423.fits". (Incidentally, I get the correct
> filename from the browser.)
> 
> Is the problem here Flask or nginx? Am I missing something? I can get
> it to work with
> 
> % wget --content-disposition ...
> 
> or to add "content_disposition = on" to a .wgetrc file, but I have a
> lot of users and would like to fix this at the source.

AFAIK that's how wget (and curl) works.  It ignores Content-Disposition
header and tries to extract file name from URL.  For wget to support
Content-Disposition header, you need to use --content-disposition (in
case of curl -J -O).

One way to solve this would be to redirect from

  http://api.sdss3.org/spectrum?id=sdss.731.52460.423.26

to something like

  http://api.sdss3.org/download/spec-0731-52460-0423.fits

if you don't mind the cost of the additional HTTP request.

-- 
Audrius Kažukauskas
http://neutrino.lt/

Re: [flask] attachment filename & wget & X-Accel-Redirect

From:
Demitri Muna
Date:
2012-09-21 @ 19:06
Hi,

On Sep 21, 2012, at 2:39 PM, Audrius Kažukauskas <audrius@neutrino.lt> wrote:

> One way to solve this would be to redirect from
> 
> http://api.sdss3.org/spectrum?id=sdss.731.52460.423.26
> 
> to something like
> 
> http://api.sdss3.org/download/spec-0731-52460-0423.fits
> 
> if you don't mind the cost of the additional HTTP request.

Yeah, that was the best I'd determined. Sad. I was hoping to avoid the 
(unnecessary) round trip to the user with a redirect back to the server. 
Is there another way I can send something like the above as a response 
directly to nginx to avoid that trip, i.e. reform the url somehow?

Cheers,
Demitri