www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - FastCGI binding or implementation?

reply Jeremy Sandell <jlsandell gmail.com> writes:
Hello!

   Does anyone know if there's a D2 binding or implementation for fastcgi as
of yet?

Thanks!
Jeremy Sandell
Oct 14 2011
next sibling parent jdrewsen <jdrewsen nospam.com> writes:
Den 15-10-2011 03:14, Jeremy Sandell skrev:
 Hello!

     Does anyone know if there's a D2 binding or implementation for
 fastcgi as of yet?

 Thanks!
 Jeremy Sandell
Adam Ruppe has a cgi module with some fastcgi in it afaik: http://arsdnet.net/dcode/cgi.d /Jonas
Oct 15 2011
prev sibling parent reply Andrea Fontana <advmail katamail.com> writes:
I'm working on a SCGI implementation for my job. SCGI is quite easy to
handle and well-supported by servers.
The only missing part is multipart POST (used for file post).

get, post, cookie, headers (etc..) just work.=20

I have to ask permission to publish my  code, btw it's a very easy
protocol to implement.
=20

Il giorno ven, 14/10/2011 alle 21.14 -0400, Jeremy Sandell ha scritto:

 Hello!
=20
=20
=20
    Does anyone know if there's a D2 binding or implementation for
 fastcgi as of yet?
=20
=20
 Thanks!
 Jeremy Sandell
Oct 17 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-17 10:14, Andrea Fontana wrote:
 I'm working on a SCGI implementation for my job. SCGI is quite easy to
 handle and well-supported by servers.
 The only missing part is multipart POST (used for file post).

 get, post, cookie, headers (etc..) just work.

 I have to ask permission to publish my code, btw it's a very easy
 protocol to implement.
What about the rest of the HTTP methods?
 Il giorno ven, 14/10/2011 alle 21.14 -0400, Jeremy Sandell ha scritto:
 Hello!


 Does anyone know if there's a D2 binding or implementation for fastcgi
 as of yet?


 Thanks!
 Jeremy Sandell
-- /Jacob Carlborg
Oct 17 2011
parent reply Andrea Fontana <advmail katamail.com> writes:
I handle request on different threads. I do some pre-processing on
scgi data and I fill a struct:

request.get[]
request.post[]
request.cookie[]
request.headers[string]

then I call a virtual function (to override on subclasses) like:

do(request, output);

where user fill output struct in a way like:

output.data ~= "<html><body><h1>hello world</h1></body></html>";
output.status = 200
output.cookies = bla bla

and then if is method != "head" i send headers + data, else just
"headers".

btw 99% of usage is get, post, head.




== Quotato dall`articolo Jacob Carlborg (doob me.com)
 On 2011-10-17 10:14, Andrea Fontana wrote:
 I'm working on a SCGI implementation for my job. SCGI is quite
easy to
 handle and well-supported by servers.
 The only missing part is multipart POST (used for file post).

 get, post, cookie, headers (etc..) just work.

 I have to ask permission to publish my code, btw it's a very
easy
 protocol to implement.
What about the rest of the HTTP methods?
 Il giorno ven, 14/10/2011 alle 21.14 -0400, Jeremy Sandell ha
scritto:
 Hello!


 Does anyone know if there's a D2 binding or implementation for
fastcgi
 as of yet?


 Thanks!
 Jeremy Sandell
Oct 17 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-17 16:01, Andrea Fontana wrote:
 I handle request on different threads. I do some pre-processing on
 scgi data and I fill a struct:

 request.get[]
 request.post[]
 request.cookie[]
 request.headers[string]

 then I call a virtual function (to override on subclasses) like:

 do(request, output);

 where user fill output struct in a way like:

 output.data ~= "<html><body><h1>hello world</h1></body></html>";
 output.status = 200
 output.cookies = bla bla

 and then if is method != "head" i send headers + data, else just
 "headers".

 btw 99% of usage is get, post, head.
Yes, but if you want to write a web site that is RESTful you need the other HTTP methods as well, at least PUT and DELETE. BTW, what about creating something like Rack but for D. Rack is a low level interface in front of the web server which web frameworks can be built on top. http://rack.github.com/ -- /Jacob Carlborg
Oct 17 2011
parent reply Jeremy Sandell <jlsandell gmail.com> writes:
On Mon, Oct 17, 2011 at 2:11 PM, Jacob Carlborg <doob me.com> wrote:

 On 2011-10-17 16:01, Andrea Fontana wrote:

 I handle request on different threads. I do some pre-processing on
 scgi data and I fill a struct:

 request.get[]
 request.post[]
 request.cookie[]
 request.headers[string]

 then I call a virtual function (to override on subclasses) like:

 do(request, output);

 where user fill output struct in a way like:

 output.data ~= "<html><body><h1>hello world</h1></body></html>";
 output.status = 200
 output.cookies = bla bla

 and then if is method != "head" i send headers + data, else just
 "headers".

 btw 99% of usage is get, post, head.
Yes, but if you want to write a web site that is RESTful you need the other HTTP methods as well, at least PUT and DELETE. BTW, what about creating something like Rack but for D. Rack is a low level interface in front of the web server which web frameworks can be built on top. http://rack.github.com/ -- /Jacob Carlborg
Yes, this is exactly why I was wondering whether FastCGI had been implemented (though SCGI works for me as well) - so that I could write something on top of it, in much the same way I would using (for example) WSGI in Python. I also agree with you re: supporting all of the HTTP methods. Just because the most common ones are GET, POST, and HEAD doesn't mean we should leave out the others; both PUT and DELETE are quite useful. Best regards, Jeremy Sandell
Oct 18 2011
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
I've been having trouble with my news postings, so forgive me if
I said this before.

But my cgi.d module supports FastCGI via the C library, with the
same D interface as normal CGI or an embedded server:

https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff

Just compile with -version=fastcgi to use that.
Oct 18 2011
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
Tale time, only tangentially on topic.


Today, I was coincidentally switching one of my work apps from
standard CGI to Fast CGI.

Almost trivial. Set up Apache, then build the program with
-version=fastcgi. Done.

Well, not 100% done. I had a piece of static data in the app
that worked correctly before but now means subsequent requests
were out of it.

Changed that to an instance variable, and boom, works perfectly.


* If you are using Fast CGI, avoid static variables.



The next thing is speed. From principles, there's very little
reason for FastCGI to actually be faster than normal CGI - the
startup costs are insignificant next to the total app runtime
and network lag. (Startup is maybe 5 ms on the live server,
with runtime close to 50ms and ping to the user another 100ms.
The "cost" of CGI is roundoff error in the actual deployment.)


My benchmarks supported this for the kind of loads we had before.


But now, the number of concurrent users is picking up. The CGI
still performed very well, though every so often, users complained
about lag on some resources.

I ran a benchmark comparing cgi to fast cgi with a very large
number of concurrent users.

It showed better availability and about a 15% speed boost under
this load. Since Apache restarts it when it segfaults, reliability
ought not to be affected, though it's too soon to say for sure.


So, I changed the makefile to say "-version=fastcgi" and soon
realized I must search for static variables - found just one,
so easy fix, and we're up on fastcgi.


... but that 15% in the benchmark hasn't translated to a big change
in the live environment yet. Been several hours now, and we've
been trying to force the availability issue, and failed so far.

Looks like a win, but not a very big one. Speed on the whole -
unaffected. The difference is roundoff error once you factor in
network lag and such again.



So, how can we speed up the application? The key here is client
side caching.

Using my cgi.d, there's a function:

cgi.setCache(true);

which tells it simply to cache the response forever. It makes
an expiration date long in the future.

Set that for any content which changes infrequently - css,
javascript, images, any kind of (conceptually) pure or static data,
etc.

Now, your code doesn't run again and the user doesn't hit the
network again. What was 150ms is now < 1ms. The users will feel
the difference.

You might set even data that changes often to cache for a few
minutes. Odds are the user doesn't need it to revalidate on the
server every minute. cgi.d's setResponseExpires can help here,
just set it a little bit in the future.

If the user hits a link to go back to a page then, it will
load from cache most the time, making navigating the site feel
snappy. Until the time expires, then it's wait again, but IMO
some cache is better than none.

Remember: you can cache AJAX responses too.




What if the resource actually does change? You'll want to change
the link. When compiling, there's a __TIMESTAMP__ special token.
A quick and dirty method is to use that __TIMESTAMP__ on your
resource URLs in your html so every time you recompile, it
invalidates the user's cache.

<script src="/myapp/functions.js?{$timestamp}"></script>



A better way might be to hash the content at compile time, but
I haven't written code that can do this well enough for real
work yet.

* Caching makes a much bigger difference than just about any other
  technique. You'll still want fast code for the cold cache users,
  but as they browse your site, a good cache policy can shave
  full seconds off the experience.

  The fastest code is running no code at all.
Oct 18 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-18 20:21, Adam D. Ruppe wrote:
 Tale time, only tangentially on topic.


 Today, I was coincidentally switching one of my work apps from
 standard CGI to Fast CGI.

 Almost trivial. Set up Apache, then build the program with
 -version=fastcgi. Done.

 Well, not 100% done. I had a piece of static data in the app
 that worked correctly before but now means subsequent requests
 were out of it.

 Changed that to an instance variable, and boom, works perfectly.


 * If you are using Fast CGI, avoid static variables.



 The next thing is speed. From principles, there's very little
 reason for FastCGI to actually be faster than normal CGI - the
 startup costs are insignificant next to the total app runtime
 and network lag. (Startup is maybe 5 ms on the live server,
 with runtime close to 50ms and ping to the user another 100ms.
 The "cost" of CGI is roundoff error in the actual deployment.)


 My benchmarks supported this for the kind of loads we had before.


 But now, the number of concurrent users is picking up. The CGI
 still performed very well, though every so often, users complained
 about lag on some resources.

 I ran a benchmark comparing cgi to fast cgi with a very large
 number of concurrent users.

 It showed better availability and about a 15% speed boost under
 this load. Since Apache restarts it when it segfaults, reliability
 ought not to be affected, though it's too soon to say for sure.


 So, I changed the makefile to say "-version=fastcgi" and soon
 realized I must search for static variables - found just one,
 so easy fix, and we're up on fastcgi.


 ... but that 15% in the benchmark hasn't translated to a big change
 in the live environment yet. Been several hours now, and we've
 been trying to force the availability issue, and failed so far.

 Looks like a win, but not a very big one. Speed on the whole -
 unaffected. The difference is roundoff error once you factor in
 network lag and such again.



 So, how can we speed up the application? The key here is client
 side caching.

 Using my cgi.d, there's a function:

 cgi.setCache(true);

 which tells it simply to cache the response forever. It makes
 an expiration date long in the future.

 Set that for any content which changes infrequently - css,
 javascript, images, any kind of (conceptually) pure or static data,
 etc.

 Now, your code doesn't run again and the user doesn't hit the
 network again. What was 150ms is now<  1ms. The users will feel
 the difference.

 You might set even data that changes often to cache for a few
 minutes. Odds are the user doesn't need it to revalidate on the
 server every minute. cgi.d's setResponseExpires can help here,
 just set it a little bit in the future.

 If the user hits a link to go back to a page then, it will
 load from cache most the time, making navigating the site feel
 snappy. Until the time expires, then it's wait again, but IMO
 some cache is better than none.

 Remember: you can cache AJAX responses too.




 What if the resource actually does change? You'll want to change
 the link. When compiling, there's a __TIMESTAMP__ special token.
 A quick and dirty method is to use that __TIMESTAMP__ on your
 resource URLs in your html so every time you recompile, it
 invalidates the user's cache.

 <script src="/myapp/functions.js?{$timestamp}"></script>



 A better way might be to hash the content at compile time, but
 I haven't written code that can do this well enough for real
 work yet.
Yeah, that's how Rails 3.1 does it now. Rails 3.1 inserts a hash of the content in the file name instead of a time stamp after the question mark.
 * Caching makes a much bigger difference than just about any other
    technique. You'll still want fast code for the cold cache users,
    but as they browse your site, a good cache policy can shave
    full seconds off the experience.

    The fastest code is running no code at all.
Why not just cache the generated HTML and let Apache handle it. Then it doesn't even need to start the application if the cache is available. -- /Jacob Carlborg
Oct 18 2011
parent reply Adam Ruppe <destructionator gmail.com> writes:
Jacob Carlborg:
 Why not just cache the generated HTML and let Apache handle it.
That sounds hard... configuring Apache to do anything beyond the most trivial of tasks is a huge pain to me. It is easy to call "cgi.setCache(true);" though.
 Then it doesn't even need to start the application if the cache is
 available.
It's better with a client side cache. If it's available, you don't have to go to the server at all! Server side caching is something I haven't done yet; it's never been useful to me.
Oct 19 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-10-19 16:36, Adam Ruppe wrote:
 Jacob Carlborg:
 Why not just cache the generated HTML and let Apache handle it.
That sounds hard... configuring Apache to do anything beyond the most trivial of tasks is a huge pain to me.
No, it's not that hard. Just add a couple of rewrite-rules that checks if a request matches an already cached page and rewrite it to the cached page. Something like this: </VirtualHost *:80> ... RailsAllowModRewrite On RewriteEngine On RewriteCond %{THE_REQUEST} ^(GET|HEAD) RewriteCond %{REQUEST_URI} ^/([^.]+)$ RewriteCond %{DOCUMENT_ROOT}/cache/%1.html -f RewriteRule ^/[^.]+$ /cache/%1.html [QSA,L] RewriteCond %{THE_REQUEST} ^(GET|HEAD) RewriteCond %{DOCUMENT_ROOT}/cache/index.html -f RewriteRule ^/$ /cache/index.html [QSA,L] </VirtualHost> I found the above at: http://www.alfajango.com/blog/make-sure-your-rails-application-is-actually-caching-and-not-just-pretending/
 It is easy to call "cgi.setCache(true);" though.

 Then it doesn't even need to start the application if the cache is
 available.
It's better with a client side cache. If it's available, you don't have to go to the server at all!
Yes of course, that is preferred.
 Server side caching is something I haven't done yet; it's never
 been useful to me.
-- /Jacob Carlborg
Oct 19 2011
prev sibling next sibling parent simendsjo <simendsjo gmail.com> writes:
On 18.10.2011 19:24, Jeremy Sandell wrote:
 On Mon, Oct 17, 2011 at 2:11 PM, Jacob Carlborg <doob me.com
 <mailto:doob me.com>> wrote:

     On 2011-10-17 16:01, Andrea Fontana wrote:

         I handle request on different threads. I do some pre-processing on
         scgi data and I fill a struct:

         request.get[]
         request.post[]
         request.cookie[]
         request.headers[string]

         then I call a virtual function (to override on subclasses) like:

         do(request, output);

         where user fill output struct in a way like:

         output.data ~= "<html><body><h1>hello world</h1></body></html>";
         output.status = 200
         output.cookies = bla bla

         and then if is method != "head" i send headers + data, else just
         "headers".

         btw 99% of usage is get, post, head.


     Yes, but if you want to write a web site that is RESTful you need
     the other HTTP methods as well, at least PUT and DELETE.

     BTW, what about creating something like Rack but for D. Rack is a
     low level interface in front of the web server which web frameworks
     can be built on top.

     http://rack.github.com/

     --
     /Jacob Carlborg


 Yes, this is exactly why I was wondering whether FastCGI had been
 implemented (though SCGI works for me as well) - so that I could write
 something on top of it, in much the same way I would using (for example)
 WSGI in Python.

 I also agree with you re: supporting all of the HTTP methods. Just
 because the most common ones are GET, POST, and HEAD doesn't mean we
 should leave out the others; both PUT and DELETE are quite useful.

 Best regards,
 Jeremy Sandell
Adam D. Ruppe has a wrapper for libfcgi at github. I started implementing fcgi, but it's basically just a very, very limited ugly-hack prototype. Doubt you'll get much use of it, but I'll attach it here anyway.
Oct 18 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-10-18 19:24, Jeremy Sandell wrote:
 On Mon, Oct 17, 2011 at 2:11 PM, Jacob Carlborg <doob me.com
 <mailto:doob me.com>> wrote:

     On 2011-10-17 16:01, Andrea Fontana wrote:

         I handle request on different threads. I do some pre-processing on
         scgi data and I fill a struct:

         request.get[]
         request.post[]
         request.cookie[]
         request.headers[string]

         then I call a virtual function (to override on subclasses) like:

         do(request, output);

         where user fill output struct in a way like:

         output.data ~= "<html><body><h1>hello world</h1></body></html>";
         output.status = 200
         output.cookies = bla bla

         and then if is method != "head" i send headers + data, else just
         "headers".

         btw 99% of usage is get, post, head.


     Yes, but if you want to write a web site that is RESTful you need
     the other HTTP methods as well, at least PUT and DELETE.

     BTW, what about creating something like Rack but for D. Rack is a
     low level interface in front of the web server which web frameworks
     can be built on top.

     http://rack.github.com/

     --
     /Jacob Carlborg


 Yes, this is exactly why I was wondering whether FastCGI had been
 implemented (though SCGI works for me as well) - so that I could write
 something on top of it, in much the same way I would using (for example)
 WSGI in Python.

 I also agree with you re: supporting all of the HTTP methods. Just
 because the most common ones are GET, POST, and HEAD doesn't mean we
 should leave out the others; both PUT and DELETE are quite useful.

 Best regards,
 Jeremy Sandell
Although I have no idea if the rest of the 9 HTTP methods are useful, e.g. trace, options, connect and patch. -- /Jacob Carlborg
Oct 18 2011
parent reply Andrea Fontana <advmail katamail.com> writes:
AFAIK other http methods have nothing special. You have just to
implement on your code:

if (request.method =3D=3D "PUT")=20
{
...
...
}

if you need them. Am i wrong?


Il giorno mer, 19/10/2011 alle 08.36 +0200, Jacob Carlborg ha scritto:

 On 2011-10-18 19:24, Jeremy Sandell wrote:
 On Mon, Oct 17, 2011 at 2:11 PM, Jacob Carlborg <doob me.com
 <mailto:doob me.com>> wrote:

     On 2011-10-17 16:01, Andrea Fontana wrote:

         I handle request on different threads. I do some pre-processing=
on
         scgi data and I fill a struct:

         request.get[]
         request.post[]
         request.cookie[]
         request.headers[string]

         then I call a virtual function (to override on subclasses) like=
:
         do(request, output);

         where user fill output struct in a way like:

         output.data ~=3D "<html><body><h1>hello world</h1></body></html=
";
         output.status =3D 200
         output.cookies =3D bla bla

         and then if is method !=3D "head" i send headers + data, else j=
ust
         "headers".

         btw 99% of usage is get, post, head.


     Yes, but if you want to write a web site that is RESTful you need
     the other HTTP methods as well, at least PUT and DELETE.

     BTW, what about creating something like Rack but for D. Rack is a
     low level interface in front of the web server which web frameworks
     can be built on top.

     http://rack.github.com/

     --
     /Jacob Carlborg


 Yes, this is exactly why I was wondering whether FastCGI had been
 implemented (though SCGI works for me as well) - so that I could write
 something on top of it, in much the same way I would using (for example=
)
 WSGI in Python.

 I also agree with you re: supporting all of the HTTP methods. Just
 because the most common ones are GET, POST, and HEAD doesn't mean we
 should leave out the others; both PUT and DELETE are quite useful.

 Best regards,
 Jeremy Sandell
=20 Although I have no idea if the rest of the 9 HTTP methods are useful,=20 e.g. trace, options, connect and patch. =20
Oct 19 2011
parent Adam Ruppe <destructionator gmail.com> writes:
Andrea Fontana:
 other http methods have nothing special
Indeed. The only thing that might get you is if the data's content type is different than the default. That's possible on POST too, though, so still nothing special. My cgi library has an enum to tell you what the requestMethod is, and it lists all the options in the standard. It, however, does not handle all possible content-types. It does x-www-form-urlencoded and multipart/form-data, so it can handle virtually all web forms out there - including file uploads - but if you want others, it'll take a minor modification. The best way to do it is probably to not attempt to parse it in the library at all, and just pass a range of raw data to the application.
Oct 19 2011