<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Steve Vinoski's Blog &#187; yaws</title>
	<atom:link href="http://steve.vinoski.net/blog/category/yaws/feed/" rel="self" type="application/rss+xml" />
	<link>http://steve.vinoski.net/blog</link>
	<description>Ask forgiveness, not permission.</description>
	<lastBuildDate>Sat, 17 Jul 2010 18:01:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Yaws 1.85 Released</title>
		<link>http://steve.vinoski.net/blog/2009/10/19/yaws-1-85-released/</link>
		<comments>http://steve.vinoski.net/blog/2009/10/19/yaws-1-85-released/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 22:52:59 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yaws]]></category>

		<guid isPermaLink="false">http://steve.vinoski.net/blog/?p=484</guid>
		<description><![CDATA[Today Klacke announced Yaws 1.85, mainly a bugfix release. You can find the list of changes and fixes at that link, but one addition in this release I wanted to point out was our new streamcontent_from_pid feature, which allows your server application code to temporarily take over the client connection socket from Yaws, thus allowing [...]]]></description>
			<content:encoded><![CDATA[<p>Today Klacke announced <a href="http://yaws.hyber.org/">Yaws 1.85</a>, mainly a bugfix release. You can find the list of changes and fixes at that link, but one addition in this release I wanted to point out was our new <code> streamcontent_from_pid</code> feature, which allows your server application code to temporarily take over the client connection socket from Yaws, thus allowing you to feed data directly to the socket without first passing it back through Yaws. Could be just the ticket for long-polling (Comet) applications, for example.</p>
<p>Prior to this release, the closest feature Yaws provided for this sort of operation was the <code>streamcontent</code> capability, which is still very useful in that it allows you to have an Erlang process deliver data back into Yaws, which in turn sends it in HTTP chunked transfer mode back to the client. For large file resources like video files or install tarballs, or for data sources where content arrives at your server in batches from a separate back-end source, or generally for resources whose sizes are not known up front, <code>streamcontent</code> is perfect because it lets you transfer the data back into Yaws in chunks, at your leisure and without having to copy all the data at once. Still, though, the data has to be sent back through Yaws, which converts it to HTTP chunks and writes it to the socket, plus in this case your only choice is chunked transfer.</p>
<p>With <code>streamcontent_from_pid</code>, you reply to the <code>out/1</code> upcall from Yaws with the HTTP reply headers and with the following special return tuple:</p>
<pre><code>{streamcontent_from_pid, MimeType, StreamPid}</code></pre>
<p>This tells Yaws that you wish to have process <code>StreamPid</code> take over the client socket in order to send data of media type <code>MimeType</code> directly back to the client. Yaws uses <code>MimeType</code> to set the HTTP <code>Content-Type</code> header, and then after sending that and all the other HTTP headers back to the client, it turns control of the client socket over to <code>StreamPid</code>. The code running within <code>StreamPid</code> must handle the following messages from Yaws:</p>
<ul>
<li><code>{ok, YawsPid}</code> tells <code>StreamPid</code> that it can proceed with using the socket. The socket is present in the original <code>Arg</code> variable passed to your <code>out/1</code> function and can be retrieved via <code>Arg#arg.clisock</code>.</li>
<li><code>{discard, YawsPid}</code> tells <code>StreamPid</code> that it shouldn&#8217;t send any data on the socket, for example because the client request was an HTTP <code>HEAD</code> request and so there is no response body.</li>
</ul>
<p>To send data, your code can choose to send chunked data or non-chunked data. To send the latter, first make sure you set the HTTP <code>Content-Length</code> header in your initial reply to Yaws, and then once Yaws calls back to your <code>StreamPid</code> process, just call:</p>
<pre><code>yaws_api:stream_process_deliver(Socket, IoList)</code></pre>
<p>or for chunked data:</p>
<pre><code>yaws_api:stream_process_deliver_chunk(Socket, IoList)</code></pre>
<p>where for both cases <code>Socket</code> is the client socket from the <code>Arg</code> and <code>IoList</code> is an iolist containing the data to be sent. The first case just calls <code>gen_tcp:send</code> and is there primarily so we can maybe someday add SSL socket support for this feature. For the second case Yaws will format the data for you for chunked transfer. Unless a <code>Content-Length</code> header is set, Yaws will assume you want chunked transfer and will set the <code>Transfer-Encoding</code> header appropriately. If you&#8217;re sending chunked data, make sure you send your final chunk using the following function:</p>
<pre><code>yaws_api:stream_process_deliver_final_chunk(Socket, IoList)</code></pre>
<p>so that Yaws knows to send the termination chunk to inform the client of the end of the transfer.</p>
<p>You can continue to call these functions from your <code>StreamPid</code> as frequently as you need to in order to deliver your data to the client. Meanwhile, the Yaws process that handed you the socket will just sit back and wait for you (non-blocking, of course). When you&#8217;re completely finished sending, just call:</p>
<pre><code>yaws_api:stream_process_end(Socket, YawsPid)</code></pre>
<p>to end the transmission and give control of the socket back to Yaws. At that point, your <code>StreamPid</code> can exit if it wishes.</p>
<p>If you try out this feature, be sure to send feedback either to me or to the <a href="https://lists.sourceforge.net/lists/listinfo/erlyaws-list">Yaws mailing list</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://steve.vinoski.net/blog/2009/10/19/yaws-1-85-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Yaws 1.82</title>
		<link>http://steve.vinoski.net/blog/2009/05/29/yaws-182/</link>
		<comments>http://steve.vinoski.net/blog/2009/05/29/yaws-182/#comments</comments>
		<pubDate>Fri, 29 May 2009 18:21:52 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[erlang]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yaws]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://steve.vinoski.net/blog/?p=425</guid>
		<description><![CDATA[Today Klacke released version 1.82 of Yaws. This is primarily a maintenance release, so nothing major has changed, except that yaws.conf and other files that used to go into etc now go into etc/yaws. For example, the default install prefix is /usr/local so for the installation on my laptop my yaws.conf file has moved from [...]]]></description>
			<content:encoded><![CDATA[<p>Today Klacke released <a href="http://sourceforge.net/mailarchive/forum.php?thread_name=4A1FA196.5060101%40tail-f.com&#038;forum_name=erlyaws-list">version 1.82 of Yaws</a>. This is primarily a maintenance release, so nothing major has changed, except that <code>yaws.conf</code> and other files that used to go into <code>etc</code> now go into <code>etc/yaws</code>. For example, the default install prefix is <code>/usr/local</code> so for the installation on my laptop my <code>yaws.conf</code> file has moved from <code>/usr/local/etc/yaws.conf</code> to <code>/usr/local/etc/yaws/yaws.conf</code>. You&#8217;ll want to make sure you move any existing conf files you might have to the new directory.</p>
<p>Various other changes and bug fixes are described in the <a href="http://yaws.hyber.org/">release notes on the main Yaws website</a>. For the previous release Klacke moved the sources from sourceforge to <a href="http://github.com/klacke/yaws">github</a>, so follow that link if you&#8217;re looking for source, and you can <a href="http://yaws.hyber.org/configuration.yaws">follow these instructions</a> to build, install, and run. If you should run into any issues or problems, please send a message to the <a href="https://lists.sourceforge.net/lists/listinfo/erlyaws-list">Yaws mailing list</a> or create a new issue on the <a href="http://github.com/klacke/yaws/issues">Yaws issue tracker</a>.</p>
<p>As far as planning for the next release goes, aside from the usual little bug fixes and enhancements and adding tests, Klacke and I noticed <a href="http://www.joeandmotorboat.com/">Joe Williams</a>&#8216;s <a href="http://www.slideshare.net/logicalstack/web-server-deathmatch-2009-erlang-factory-joe-williams">recent Erlang Factory presentation</a> that mentions Yaws CPU usage is sometimes higher than expected, so we&#8217;ll be looking into that and doing some general profiling and performance testing work.</p>
]]></content:encoded>
			<wfw:commentRss>http://steve.vinoski.net/blog/2009/05/29/yaws-182/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sendfile for Yaws</title>
		<link>http://steve.vinoski.net/blog/2009/01/05/sendfile-for-yaws/</link>
		<comments>http://steve.vinoski.net/blog/2009/01/05/sendfile-for-yaws/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 07:22:54 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[erlang]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yaws]]></category>

		<guid isPermaLink="false">http://steve.vinoski.net/blog/?p=211</guid>
		<description><![CDATA[A few months back Klacke gave me committer rights for Yaws. I&#8217;ve made a few fixes here and there, including adding support for passing &#8220;*&#8221; as the request URI for OPTIONS, enabling OPTIONS requests to be dispatched to appmods and yapps, and completing a previously-submitted patch for configuring the listen backlog. Klacke has just started [...]]]></description>
			<content:encoded><![CDATA[<p>A few months back Klacke gave me committer rights for <a href="http://yaws.hyber.org/">Yaws</a>. I&#8217;ve made a few fixes here and there, including adding support for <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2">passing &#8220;*&#8221; as the request URI for OPTIONS</a>, enabling OPTIONS requests to be dispatched to <a href="http://yaws.hyber.org/appmods.yaws">appmods</a> and <a href="http://yaws.hyber.org/yapp_intro.yaws">yapps</a>, and completing a <a href="http://sourceforge.net/mailarchive/forum.php?thread_name=48DA651E.80708%40lionet.info&#038;forum_name=erlyaws-list">previously-submitted patch for configuring the listen backlog</a>. Klacke has just started putting a test framework into the codebase and build system so that contributors can include tests with any patches or new code they submit, and I&#8217;ve contributed to that as well.</p>
<p>The biggest feature I&#8217;ve added to date, though, is a new linked-in driver that allows Yaws to use the <a href="http://www.freebsd.org/cgi/man.cgi?query=sendfile&#038;sektion=2">sendfile system call</a> on Linux, OS X, and FreeBSD. I never wrote a linked-in driver before, so I was happy and fortunate to have an Erlang expert like Klacke providing hints and reviewing my code.</p>
<p>I did some preliminary testing that showed that sendfile definitely improves CPU usage across the board but depending on file size, sometimes does so at the cost of increasing request times. I used my otherwise idle 2-core 2.4GHz Ubuntu 8.04.1 Dell box with 2 GB of RAM, and ran Apache Bench (ab) from another Linux host to simulate 50 concurrent clients downloading a 64k data file a total of 100000 times. I saw that user/system CPU on the web host tended to run around 33%/28% without sendfile, while with sendfile it dropped to 22%/17%. The trade-off was request time, though, where each request for the 64k file averaged 0.928ms with sendfile but 0.567ms without. With larger files, however, sendfile is slightly faster and still has better CPU usage. For example, with a 256k file, sendfile averaged 2.251ms per request with user/system CPU at 8%/16% whereas it was 2.255ms and 16%/27% CPU without sendfile, which makes me wonder if the figures for the 64k file are outliers for some reason. I performed these measurements fairly quickly, so while I believe they&#8217;re reasonably accurate, don&#8217;t take them as formal results.</p>
<p>On my MacBook Pro laptop running OS X 10.5.6, CPU usage didn&#8217;t seem to differ much whether I used sendfile or not, but requests across the board tended to be slightly faster with sendfile.</p>
<p>I ran FreeBSD 7.0.1 in a Parallels VM on my laptop, and there I saw significantly better system CPU usage with sendfile than without, sometimes as much as a 30% improvement. Requests were also noticeably faster with sendfile than without, sometimes by as much as 17%, and again depending on file size, with higher improvements for larger files. User CPU was not a factor. All in all, though, I don&#8217;t know how much the fact that I ran all this within a VM affected these numbers.</p>
<p>Given that Yaws is often used for delivering mainly dynamic content, sendfile won&#8217;t affect those cases. Still, I think it&#8217;s nice to have it available for the times when you do have to deliver file-based content, especially if the files are of the larger variety. Anyway, I committed this support to the <a href="http://erlyaws.svn.sourceforge.net/viewvc/erlyaws/trunk/yaws/">Yaws svn repository</a> back around December 21 or so. If you&#8217;d like to do your own testing, please feel free &mdash; I&#8217;d be interested in learning your results. Also, if you have ideas for further tests I might try, please leave a comment to let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://steve.vinoski.net/blog/2009/01/05/sendfile-for-yaws/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Detailed RESTful Yaws Service</title>
		<link>http://steve.vinoski.net/blog/2008/04/10/detailed-restful-yaws-service/</link>
		<comments>http://steve.vinoski.net/blog/2008/04/10/detailed-restful-yaws-service/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 06:35:06 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[yaws]]></category>
		<category><![CDATA[implementation]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://steve.vinoski.net/blog/?p=59</guid>
		<description><![CDATA[Nick Gerakines has posted a detailed example of a RESTful web service implemented using Erlang and Yaws. It provides a lot of implementation information that I didn&#8217;t have room for in my InfoQ article on this topic. Sam&#8217;s issue isn&#8217;t addressed here either, but no matter, the details of Nick&#8217;s example are worth examining nonetheless.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.socklabs.com/">Nick Gerakines</a> has posted a <a href="http://blog.socklabs.com/2008/04/a_restful_web_service_demo_in/">detailed example of a RESTful web service implemented using Erlang and Yaws</a>. It provides a lot of implementation information that I didn&#8217;t have room for in <a href="http://www.infoq.com/articles/vinoski-erlang-rest">my InfoQ article on this topic</a>.</p>
<p><a href="/blog/2008/04/03/erlang-yaws-and-etags/">Sam&#8217;s issue isn&#8217;t addressed</a> here either, but no matter, the details of Nick&#8217;s example are worth examining nonetheless.</p>
]]></content:encoded>
			<wfw:commentRss>http://steve.vinoski.net/blog/2008/04/10/detailed-restful-yaws-service/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Erlang, Yaws, and ETags</title>
		<link>http://steve.vinoski.net/blog/2008/04/03/erlang-yaws-and-etags/</link>
		<comments>http://steve.vinoski.net/blog/2008/04/03/erlang-yaws-and-etags/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 04:04:28 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[yaws]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[services]]></category>

		<guid isPermaLink="false">http://steve.vinoski.net/blog/2008/04/03/erlang-yaws-and-etags/</guid>
		<description><![CDATA[Regarding my &#8220;RESTful Services with Erlang and Yaws&#8221; article on InfoQ.com, Sam Ruby said: This otherwise excellent article fails my ETag test. When Sam speaks, I listen, so I&#8217;ve given his feedback a lot of thought. As I wrote in a comment on Sam&#8217;s blog, the Erlang/Yaws RESTful services I work on do indeed support [...]]]></description>
			<content:encoded><![CDATA[<p>Regarding my <a href="http://www.infoq.com/articles/vinoski-erlang-rest">&#8220;RESTful Services with Erlang and Yaws&#8221; article</a> on <a href="http://www.infoq.com/">InfoQ.com</a>, <a href="http://intertwingly.net/blog/2008/03/31/RESTful-Services-with-Erlang-and-Yaws">Sam Ruby said</a>:</p>
<blockquote><p><em>This otherwise excellent article fails my <a href="http://intertwingly.net/blog/2006/06/05/Elevator-Pitch">ETag test</a>.</em></p></blockquote>
<p>When Sam speaks, I listen, so I&#8217;ve given his feedback a lot of thought.</p>
<p>As I wrote in a comment on Sam&#8217;s blog, the Erlang/Yaws RESTful services I work on do indeed support conditional GETs, so at least my day-to-day work passes his ETags test. As for the article, there are two ways to think about it:</p>
<ol>
<li>
<p>If you focus on the &#8220;RESTful Design&#8221; portion of the article, then yes, I could have added a &#8220;think about where you need to support conditional GETs&#8221; item to the &#8220;key areas to pay attention to&#8221; list.</p>
</li>
<li>
<p>If you focus on the Yaws/Erlang aspect of the article, then keep in mind that dealing with ETags requires dealing with HTTP headers such as <code><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26">If-none-match</a></code> and the <code><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">ETag</a></code> header itself. The article already shows you how to read request headers and write reply headers, though, and how you actually create specific ETag values for use in the headers depends on the particulars of your resources &mdash; <a href="http://www.oreilly.com/catalog/9780596529260/">Leonard Richardson&#8217;s and Sam&#8217;s excellent book</a> already covers this pretty well.</p>
</li>
</ol>
<p>I intended the focus of the article to be more about item 2 than item 1, so I think not specifically addressing ETags is OK.</p>
<p>One thing I should have included, though, is how to parse <code>POST</code> data. You use the <code>yaws_api:parse_post/1</code> function for that, passing in an <code>arg</code> record. For typical form data, it&#8217;ll give you back a list of key/value pairs over which you can iterate, or from which you can extract expected key/value pairs using <code>yaws_api:postvar/2</code> (or even <code>proplists:lookup/2</code> or <code>lists:keysearch/3</code>, if you like). See the <a href="http://yaws.hyber.org/">documentation at the Yaws website</a> for more details, but all in all, handling <code>POST</code> data in Yaws is fairly trivial.</p>
]]></content:encoded>
			<wfw:commentRss>http://steve.vinoski.net/blog/2008/04/03/erlang-yaws-and-etags/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
