[Ur] Ur Digest, Vol 66, Issue 3

William Blair wdblair at bu.edu
Tue Aug 5 14:10:14 EDT 2014


> The second reason is the ability to control the [serve] function's
> behavior. For example, my application should serve the firmware
> tarballs to authorized users only. Authorization routine requires
> parsing of fingerprint of the user's system and searching here and
> there in the database. Integrating such things into Apache may be
> tricky (actually, I have no idea how to communicate with Apache. May
> cookies be used for that?).

Since Ur/Web allows you to set response headers, I think you could utilize
the X-Sendfile header to authorize downloads for specific users. Suppose
you're running Ur/Web  behind nginx or Apache. When you handle a request
that leads to downloading a file, you first perform all the
authorization in your
request handler. If the user authorized, you determine the file you want to send
them and then simply set the X-Sendfile header to start a download.

I don't think I really grasp Ur/Web's header interface, but I think
this could be
accomplished with something like the following

     if authorized then let
         val sendfile = blessResponseHeader "X-Sendfile"
        in
           setHeader sendfile "path/to/file";
           return <xml>Authorized</xml>
        end
     else
        return 403_error ()

Once your web server sees this header, it will ignore the application's response
and instead start to send the file directly to the user. Meanwhile,
your application
will be available to take more requests.

I personally prefer sending files this way. If other people are interested,
here are some links to configure the special header in a few web servers.

Apache
https://tn123.org/mod_xsendfile/

nginx
http://wiki.nginx.org/XSendfile

lighttpd
http://redmine.lighttpd.net/projects/1/wiki/X-LIGHTTPD-send-file

Thanks,
Will

On Tue, Aug 5, 2014 at 12:00 PM,  <ur-request at impredicative.com> wrote:
> Send Ur mailing list submissions to
>         ur at impredicative.com
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
> or, via email, send a message with subject or body 'help' to
>         ur-request at impredicative.com
>
> You can reach the person managing the list at
>         ur-owner at impredicative.com
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Ur digest..."
>
>
> Today's Topics:
>
>    1. Re: socket detaching (Sergey Mironov)
>    2. Re: socket detaching (Adam Chlipala)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Tue, 5 Aug 2014 12:57:10 +0400
> From: Sergey Mironov <grrwlf at gmail.com>
> To: The Ur programming language <ur at impredicative.com>
> Subject: Re: [Ur] socket detaching
> Message-ID:
>         <CAMOkk_bAG7uGfB432OPMyV8HmBLDwnZ9rLDstocy1kJxvnTs3w at mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8
>
> Well, I really prefer not to use Apache for serving anything but the
> completely static pages.
>
> The first reason for this is the installation procedure of my
> application. Basically, I want it to be as short as possible.
> Installation of mlton/postgre/urweb chain is straightforward and the
> correctness may be checked by simply running the application
> (excellent thing - it fails to start if something is wrong with
> postgres). The Apache-based design falls out of the scope of this
> 'check by running' method. Without Apache installation manual becomes
> shorter and system administrator - less angry.
>
> The second reason is the ability to control the [serve] function's
> behavior. For example, my application should serve the firmware
> tarballs to authorized users only. Authorization routine requires
> parsing of fingerprint of the user's system and searching here and
> there in the database. Integrating such things into Apache may be
> tricky (actually, I have no idea how to communicate with Apache. May
> cookies be used for that?).
>
> I think you will say that I am talking about non-static content and
> all non-static content should be stored in the database completely.
> Well, for the most of the applications - maybe. But sometimes
> application should interact with file-based backends and in those
> cases controlling the [serve] logic is very desirable. For my
> application, I am doing it via [val serveTarball : string ->
> transaction page] right from the [main] function.
>
> Regards,
> Sergey
>
>
>
> 2014-08-01 22:32 GMT+04:00 Adam Chlipala <adamc at csail.mit.edu>:
>> Thanks for the interesting idea.  I have to admit, I'm perplexed as to why
>> you didn't just use a traditional web server to serve such files.
>>
>> I think I'll take this opportunity to solicit community input on this
>> general issue, which has bothered me for a while.  People seem to be
>> assuming that it is axiomatically impossible or clearly undesirable that an
>> Ur/Web application must always be running in the context of a web server
>> like Apache.  Why is that? Unsurprisingly, in such a setting, it is quite
>> trivial to do anything that web servers usually do.  As far as I understand,
>> almost all real-world web applications run in the context of Apache or
>> similar servers, or at least they did 5 years ago.
>>
>> There are at least three easy modes for running Ur/Web applications with
>> Apache, lighttpd, etc.:
>> 1) FastCGI process started and stopped automatically by the web server.  I
>> recommend this mode for production deployments.
>> 2) Main web server proxies appropriate HTTP requests to the application.  I
>> recommend this mode for development.
>> 3) CGI program invoked by main web server.  This is a pretty retro option
>> that is rarely appropriate today.
>>
>> The Ur/Web manual contains example configuration for some of these
>> strategies, and I could add more, if I've been mistakenly assuming that some
>> small piece of Apache knowledge is widely enough known that it's not a big
>> deal for any Ur/Web user to apply it in setting up a development/production
>> environment.
>>
>>
>> On 08/01/2014 03:47 AM, Sergey Mironov wrote:
>>>
>>> Hi, Adam. Since you have published your file-serving extension, I'd
>>> like to share my old code for solving similar task.
>>>
>>> The idea is to be able to pickpocket the client-connection socket from
>>> the urweb and pass it to some standalone application which would use
>>> it to serve large file. I am using it to send firmware tarballs
>>> (approx 20-50 Mb in size) to the clients.
>>>
>>> Here is how it works in more details:
>>> 1. The Ur/Web server sets the 'sock' field of the uw_context (see the
>>> patch)
>>> 2. The program calls the detachSocket function which extracts this
>>> field and prevents Ur/Web from writing anything to this socket.
>>> 3. The client program starts new process (via my urweb-callback FFI
>>> library) and passes the socket to it via command line (UNIX layer
>>> makes sure that child processes inherit opened handles correctly)
>>> 4. The child process does it job to sending it's content to client
>>>
>>> That's it. I'm not asking you to include this modification into the
>>> Ur/Web, just want to share the approach.
>>>
>>> Regards,
>>> Sergey
>>>
>>> Demo - https://github.com/grwlf/urweb-detach
>>> Patch -
>>> https://github.com/grwlf/urweb-detach/blob/master/1_of_1_Introduce__Detach__mechanism_.patch
>>> (and in attachment)
>>
>>
>> _______________________________________________
>> Ur mailing list
>> Ur at impredicative.com
>> http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
>
>
>
> ------------------------------
>
> Message: 2
> Date: Tue, 05 Aug 2014 09:20:39 -0400
> From: Adam Chlipala <adamc at csail.mit.edu>
> To: ur at impredicative.com
> Subject: Re: [Ur] socket detaching
> Message-ID: <53E0DA27.9050305 at csail.mit.edu>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
> On 08/05/2014 04:57 AM, Sergey Mironov wrote:
>> Well, I really prefer not to use Apache for serving anything but the
>> completely static pages.
>
> OK; I wasn't sure if your example files being served were generated
> dynamically or not.
>
>> The second reason is the ability to control the [serve] function's
>> behavior. For example, my application should serve the firmware
>> tarballs to authorized users only. Authorization routine requires
>> parsing of fingerprint of the user's system and searching here and
>> there in the database. Integrating such things into Apache may be
>> tricky (actually, I have no idea how to communicate with Apache. May
>> cookies be used for that?).
>>
>> I think you will say that I am talking about non-static content and
>> all non-static content should be stored in the database completely.
>> Well, for the most of the applications - maybe. But sometimes
>> application should interact with file-based backends and in those
>> cases controlling the [serve] logic is very desirable. For my
>> application, I am doing it via [val serveTarball : string ->
>> transaction page] right from the [main] function.
>
> But you can use the FFI to produce Ur values of [blob] type in any way
> you like, and then you can use [returnBlob] to serve them -- there's no
> need to intercept sockets.
>
> Did you just ask the socket detaching as an optimization?  Did it make
> an important performance difference in practice?
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Ur mailing list
> Ur at impredicative.com
> http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
>
>
> ------------------------------
>
> End of Ur Digest, Vol 66, Issue 3
> *********************************



More information about the Ur mailing list