Snap Framework Bloghttp://snapframework.com/blog/blog/feed.xml2016-08-07T14:22:00-0400Snap Frameworksnap@snapframework.com/static/icon.pnghttp://snapframework.com/blog/2016/08/07/snap-1.0-releasedAnnouncing: Snap 1.02016-08-07T14:22:00-0400Doug Beardsleymightybyte@gmail.com<div class="markdown">
<p>The Snap team is delighted to announce the anxiously awaited release of version 1.0 of the Snap Web Framework for Haskell. Snap has been used in stable production applications for years now, and with this release we’re updating our version number to reflect the stability and commitment to backwards compatibility that our users depend on. Here is a summary of the major changes:</p><ul><li><p>Web server rewritten with the more efficient <a href="http://hackage.haskell.org/package/io-streams">io-streams</a>.</p></li><li><p><a href="https://snapframework.github.io/snap-code-coverage/snap-server/hpc-ghc-8.0.1/hpc_index.html">100% web server test coverage</a> makes Snap the most robust and well tested Haskell web server.</p></li><li><p>Better exception safety with <a href="http://hackage.haskell.org/package/monad-control">monad-control</a>.</p></li><li>Continued strong commitment to backwards compatibility:<ul><li>Very few breaking API changes</li><li><a href="https://travis-ci.org/snapframework/snap">Built and tested with the last 5 major GHC versions</a></li></ul></li></ul><h2 id="the-details">The Details</h2><h3 id="now-backed-by-io-streams">Now backed by io-streams</h3><p>Snap’s web server has been overhauled, replacing the enumerator package with the newer, leaner, faster, and easier to use <a href="http://hackage.haskell.org/package/io-streams">io-streams</a>. If you were using of Snap’s low-level enumerator functions, those will need to be migrated to io-streams. Otherwise there should be few interface changes.</p><h3 id="more-modular-project-template-infrastructure">More modular project template infrastructure</h3><p>The snap executable that generates project templates has been moved from the snap package to snap-templates. Your snap applications depending on snap will continue to do so, but with a slightly lighter set of transitive dependencies. If you want to run <code>snap init</code> to generate a project template, you will now need to do <code>cabal install snap-templates</code> first instead of <code>cabal install snap</code>.</p><h2 id="migration-guide">Migration Guide</h2><ul><li><p>Change your cabal files to depend on monad-control instead of MonadCatchIO-transformers.</p></li><li><p>Instead of deriving the MonadCatchIO type class, you should now make MonadBaseControl instances. Depending on your monad, this may require MonadBase and MonadTransControl instances as well. For examples of how to do that for common monad structures, look at <a href="https://github.com/snapframework/heist/blob/master/src/Heist/Internal/Types/HeistState.hs#L362">Heist</a> and snap (<a href="https://github.com/snapframework/snap/blob/master/src/Snap/Snaplet/Internal/Types.hs#L283">here</a>, <a href="https://github.com/snapframework/snap/blob/master/src/Snap/Snaplet/Internal/Lensed.hs#L103">here</a>, and <a href="https://github.com/snapframework/snap/blob/master/src/Snap/Snaplet/Internal/RST.hs#L114">here</a>).</p></li><li><p>Any exception handling functions like <code>try</code>, <code>catch</code>, etc you were using from Control.Monad.CatchIO should now come from Control.Exception.Lifted which is provided by the lifted-base package.</p></li><li><p><code>initCookieSessionManager</code> takes an additional <code>Maybe ByteString</code> argument representing an optional cookie domain. Passing Nothing as the new argument will give the same behavior as you had before.</p></li></ul><h2 id="outline">Outline</h2><p>The Snap Framework is composed of five major packages:</p><ul><li><p><a href="http://hackage.haskell.org/package/snap-core">snap-core</a> - A simple and stable web server API.</p></li><li><p><a href="http://hackage.haskell.org/package/snap-server">snap-server</a> - A robust and well tested web server implementing the snap-core API.</p></li><li><p><a href="http://hackage.haskell.org/package/heist">heist</a> - An HTML 5 template system allowing designers to make changes to markup without needing to have a Haskell toolchain installed and recompile the app.</p></li><li><p><a href="http://hackage.haskell.org/package/snap">snap</a> - Umbrella project that integrates the above three packages, provides a snaplet system for building reusable web components, and includes built-in snaplets for common things like sessions, auth, templating, etc.</p></li><li><p><a href="http://hackage.haskell.org/package/snap-templates">snap-templates</a> - Provides an executable for generating Snap project templates.</p></li></ul><h2 id="acknowledgments">Acknowledgments</h2><p>We would like to thank the dozens of contributors who have helped over the years to get Snap to this milestone. Particular thanks go to Greg Hale who has been instrumental in getting us across the finish line for this release.</p>
</div>2016-08-07T14:22:00-0400Release notes for Snap 1.0http://snapframework.com/blog/2014/09/24/heist-0.14-releasedAnnouncing: Heist v0.142014-09-24T06:10:00-0400Doug Beardsleymightybyte@gmail.com<div class="markdown">
<p>The Snap team is happy to announce the release of version 0.14 of Heist.</p><h2 id="major-changes">Major Changes</h2><h3 id="namespace-support">Namespace Support</h3><p>Heist now has support for namespaces. This allows you to configure Heist so that all of your splices require a namespace. Requiring a namespace allows Heist to be more aggressive with errors for unbound splices. For instance, imagine you set the hcNamespace field in your HeistConfig to “h”, and you bind two splices.</p><pre class="sourceCode haskell"><code class="sourceCode haskell">mySplices <span class="fu">=</span> <span class="kw">do</span>
<span class="st">"foo"</span> <span class="fu">#!</span> fooSplice
<span class="st">"bar"</span> <span class="fu">#!</span> barSplice</code></pre><p>With this setup, you would put the “h” namespace on all of the splice tags in your templates. Instead of calling those splices with “<foo>” and “<bar>”, you would use “<h:foo>” and “<h:bar>”. So why go to all this trouble so you have to type more? Because it allows Heist to do more error checking. Without namespaces there is no way for Heist to know whether a tag is supposed to be a splice or not. We could use the list of valid HTML tags to infer it, but that significantly constrains the scope of what we intended for Heist. This approach allows the user to be explicit about which tags should be splices. If you do not want to use namespaces, set the namespace to the empty string.</p><p>Along with the namespace field, we introduced the <code>hcErrorNotBound</code> for controlling the error checking. When <code>hcErrorNotBound</code> is <code>True</code>, Heist will generate an error message if it encounters any namespaced tags that do not have splices bound for them. This eliminates a large class of bugs where users were using a splice in their templates, but forgot to bind it in their code. The intent is that users will usually want to have this error checking turned on. But we felt it was also important to be able to use namespacing without the strict enforcement, so we included this flag to give users full control.</p><h3 id="generalized-error-reporting">Generalized Error Reporting</h3><p>Since this release is doing more error checking, we decided to expose error facilities to the user. This release exposes a new function <code>tellSpliceError</code> that you can use when error conditions are detected in your splices. If you are using compiled Heist, then all your templates will be processed up front at load time. If any of your load time or compiled splices detect an error condition that the user needs to fix, you can call <code>tellSpliceError</code> with an error message. If there are any errors, Heist initialization will fail and all the errors will be returned.</p><h3 id="restructured-heistconfig">Restructured HeistConfig</h3><p>The addition of <code>hcNamespace</code> and <code>hcErrorNotBound</code> to HeistConfig required some restructuring. Previously HeistConfig had a Monoid instance, but we removed that since the new fields make it unclear which instance should be used. But we also did not want to completely get rid of the monoid functionality either. So in order to get the best of both worlds, we refactored all of HeistConfig’s previous fields into another data structure called SpliceConfig. This way we can keep the Monoid instance for SpliceConfig and still avoid imposing a weird set of semantics on the user.</p><p>Unfortunately, given the use of field accessors it was impossible to make this change without breaking backwards compatibility. What seems like it should have been a simple addition of a couple parameters ended up being a more significant refactoring. To make these kinds of changes easier in the future Heist now exports lenses to all of the HeistConfig fields as well as an <code>emptyHeistConfig</code> value to use as a starting point. These lenses work with both the lens and lens-family-core packages and we export them without incurring a dependency on either lens package.</p><p>The HeistConfig constructor and field accessors have been moved to the Heist.Internal.Types module, so if you really need them, they are still available. However, be aware that Internal modules are subject to change without the deprecation cycle that we use for other modules.</p><h2 id="minor-improvements">Minor improvements</h2><ul><li><p>Factored out SpliceAPI module into separate map-syntax package and deprecated the old module which will be removed in the next major release.</p></li><li><p>Snap has been updated to support this Heist 0.14.</p></li></ul>
</div>2014-09-24T06:10:00-0400Release notes for Heist 0.14http://snapframework.com/blog/2013/09/09/snap-0.13-releasedAnnouncing: Snap Framework v0.132013-09-09T14:10:00-0400Doug Beardsleymightybyte@gmail.com<div class="markdown">
<p>The Snap team is happy to announce the release of version 0.13 of the Snap Framework. We would like to thank Edward Kmett who helped with some of the broad design ideas incorporated in this release.</p><p>The Heist API changed significantly in this release. If you are migrating an existing app to 0.13, check out the following diffs to see how the migration was done in some real packages.</p><ul><li><a href="https://github.com/jaspervdj/digestive-functors/compare/cc2ae4e3ff94b335444d27fdc0533c102ba98e1a...5a9d3fb75be6db58145f00b06c763a06f7b50f6c">digestive-functors-heist</a></li><li><a href="https://github.com/ozataman/snap-extras/compare/e44057dbe3d622883d1ea44bb3a97d5465e6049a...557ea1882a485f3509200db7d5733fef6f9cfc70">snap-extras</a></li></ul><h2 id="major-changes">Major Changes</h2><ul><li><p>The API for compiled Heist has now stabilized. The new API is much simpler than the old one. The old API had inconsistent use of <code>n a</code>, <code>RuntimeSplice n a</code>, and <code>Promise a</code>, which made it difficult to understand how things should be composed. Since those three things are different incarnations of roughly the same general idea, we were able to simplify the high-level API to just use <code>RuntimeSplice n a</code> everywhere.</p></li><li><p>The low level Heist API was moved to its own module. The high-level API referred to above is much simpler, but slightly restricted in its power. If you need to write compiled splices with special control flow, then you will need to import the low level API and work with promises directly.</p></li><li><p>Heist now has new syntax for writing splices. The old alist syntax made behavior unclear when the same splice name occurred more than once. Also, the actual syntax for alists is not incredibly clean either. The new syntax is defined in the Heist.SpliceAPI module and leverages do notation and a few infix operators to create elegant syntax for defining splices while at the same time making semantics more clear.</p></li><li><p>The snaplet testing API has been modified to allow you to choose an environment.</p></li></ul><h2 id="bugfixes-minor-improvements">Bugfixes / minor improvements</h2><ul><li><p>Fixed doctype handling in compiled templates.</p></li><li><p>We added a new function getEnvironment to Snap.Snaplet that allows snaplets to get the current environment.</p></li></ul>
</div>2013-09-09T14:10:00-0400Release notes for Snap 0.13http://snapframework.com/blog/2013/05/15/snap-0.12-releasedAnnouncing: Snap Framework v0.122013-05-15T20:15:00-0400Doug Beardsleymightybyte@gmail.com<div class="markdown">
<p>The Snap team is happy to announce the release of version 0.12 of the Snap Framework.</p><h2 id="new-features">New features</h2><ul><li><p>Heist now has the ability to reload templates. Along with this, <code>HeistConfig</code> now stores template locations instead of templates. A template location is essentially an IO action returning templates. This allows you to have Heist get its templates from a database, over the network, etc–anything that can be done from IO.</p></li><li><p>The Heist snaplet now has generic functions that can work with either interpreted or compiled templates. Most applications will choose one of either interpreted or compiled templates and not need this new functionality. However, if you are writing a generic snaplet, then you probably want it to work no matter which mode the end application uses. All you need to do is import the <code>Snap.Snaplet.Heist.Generic</code> module. The Heist snaplet defaults to compiled mode. If you want to use interpreted mode, call the <code>setInterpreted</code> function in your application initializer.</p></li><li><p>It is now possible to reload individual snaplets without reloading the whole site. The snaplet API now includes a function <code>modifyMaster</code> that you can use to write reload functions for individual snaplets. The Heist snaplet now provides a reloader leveraging this functionality. We found this very useful in allowing us to rapidly iterate when making changes to markup in large applications that take a long time to initialize.</p></li></ul><h2 id="bugfixes-minor-improvements">Bugfixes / minor improvements</h2><ul><li><p>Generalized parts of the compiled splice API to use <code>RuntimeSplice n a</code> instead of the less general <code>n a</code>. Since RuntimeSplice is a monad transformer, this change only requires you to add a call to <code>lift</code> in places where you have an <code>n a</code>.</p></li><li><p>Fixed Heist’s <code>runAttributesRaw</code> function to do both types of attribute parsing.</p></li><li><p>Fixed Heist bug that caused XML templates to be rendered as HTML5.</p></li><li><p>Improve the consistency of the auth snaplet API.</p></li><li><p>Eliminated the inappropriate export of orphan instances.</p></li></ul>
</div>2013-05-15T20:15:00-0400Release notes for Snap 0.12http://snapframework.com/blog/2013/03/05/announcing-io-streamsAnnouncing: first release of io-streams2013-03-05T22:59:00+0100Gregory Collinsgreg@gregorycollins.net<div class="markdown">
<p>After more than eight months of careful design and development, The Snap Framework team is happy to announce the first version of <a href="http://hackage.haskell.org/package/io-streams"><code>io-streams</code></a>, a simple and easy-to-use library for doing streaming I/O in Haskell.</p><p>The <code>io-streams</code> library is based around two basic types, <code>InputStream a</code> and <code>OutputStream a</code>, and three fundamental I/O primitives:</p><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="co">-- read an item from an input stream</span>
<span class="fu">read</span><span class="ot"> ::</span> <span class="dt">InputStream</span> a <span class="ot">-></span> <span class="dt">IO</span> (<span class="dt">Maybe</span> a)
<span class="co">-- push an item back to an input stream</span>
<span class="ot">unRead ::</span> a <span class="ot">-></span> <span class="dt">InputStream</span> a <span class="ot">-></span> <span class="dt">IO</span> ()
<span class="co">-- write to an output stream</span>
<span class="ot">write ::</span> <span class="dt">Maybe</span> a <span class="ot">-></span> <span class="dt">OutputStream</span> a <span class="ot">-></span> <span class="dt">IO</span> ()</code></pre><p>Streams can be transformed by composition and hooked together with a large set of provided combinators:</p><pre class="sourceCode"><code>ghci> Streams.fromList [1,2,3::Int] >>= Streams.map (*10) >>= Streams.toList
[10,20,30]</code></pre><p>Stream composition leaves the original stream accessible:</p><pre class="sourceCode"><code>ghci> input <- Streams.fromByteString "long string"
ghci> wrapped <- Streams.takeBytes 4 input
ghci> Streams.read wrapped
Just "long"
ghci> Streams.read wrapped
Nothing
ghci> Streams.read input
Just " string"</code></pre><p>Simple types and operations in the <code>IO</code> monad mean straightforward and simple exception handling and resource cleanup using Haskell standard library functions like <code>bracket</code>.</p><p>The <code>io-streams</code> library comes with:</p><ul><li>functions to use files, handles, concurrent channels, sockets, lists, vectors, and more as streams.</li><li>a plethora of combinators for wrapping and transforming streams, including compression and decompression using <code>zlib</code>, controlling precisely how many bytes are read from or written to a stream, buffering output using bytestring builders, folds, maps, filters, zips, etc.</li><li>support for parsing from streams using <a href="http://hackage.haskell.org/package/attoparsec">attoparsec</a>.</li></ul><p>For first-time users, <code>io-streams</code> comes with an included tutorial in the <code>System.IO.Streams.Tutorial</code> module, written by <a href="http://www.haskellforall.com/">Gabriel Gonzalez</a> of “<a href="http://hackage.haskell.org/package/pipes">pipes</a>” fame.</p><p>The <code>io-streams</code> library is tested on GHC 7.0, 7.2, 7.4, and 7.6, and includes an extensive test suite with 100% function, statement, and branch coverage:</p><div class="figure"><img src="io-streams-test-coverage.png" alt="Haskell program coverage report for io-streams 1.0.0.0" /><p class="caption">Haskell program coverage report for io-streams 1.0.0.0</p></div><p>The <code>io-streams</code> library was written to serve as the I/O subsystem underpinning the next release of the Snap Framework web programming library and server. It also serves as the basis behind the excellent new <a href="https://github.com/afcowie/http-streams">http-streams</a> HTTP client library written by <a href="http://blogs.operationaldynamics.com/andrew/">Andrew Cowie</a>, which will also be released shortly, along with the <a href="http://hackage.haskell.org/package/openssl-streams">openssl-streams</a> for interfacing <a href="http://hackage.haskell.org/package/HsOpenSSL">HsOpenSSL</a> with <code>io-streams</code>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><p><em>Q.</em> Why yet another library for doing streaming I/O? Aren’t iteratees/pipes/conduits enough?</p><p><em>A.</em> There are two motivating differentiators that led me to write <code>io-streams</code>: the other libraries were too difficult to understand, and their use of continuation-passing style interacts badly with asynchronous exceptions.</p><p><em>Q.</em> What is the resource-handling strategy used by <code>io-streams</code>?</p><p><em>A.</em> In nearly all cases, resources (<code>Socket</code>s, <code>Handle</code>s, etc.) are not managed directly by <code>io-streams</code>. You can think of an <code>InputStream</code> as a little state machine that you attach to an underlying resource. Instead, you can use standard Haskell exception-handling strategies like <code>bracket</code> to acquire resources, hand them to <code>io-streams</code>, perform streaming computations, and then clean up afterwards.</p><p>Since you manage resources and everything happens in a direct style in the <code>IO</code> monad, you can be sure that e.g. opening a temporary file halfway through a streaming computation and cleaning it up using <code>bracket</code> is always exception-safe.</p><p><em>Q.</em> Why isn’t <code>io-streams</code> written in monad transformer style?</p><p><em>A.</em> A couple of reasons:</p><ul><li>to keep the library as simple as possible. Even beginners should be able to understand and use <code>io-streams</code> without too much trouble.</li><li>I’m coming to the conclusion in my own code that monad transformers are OK in small doses, but are often overused, especially where very large monad transformer stacks are concerned. Each level added to a monad transformer stack is a performance tax on every line of every monadic function.</li></ul><p>I realize that this may make <code>io-streams</code> inappropriate for use with resources that have operations in some other monad lifted over <code>IO</code>; I’m more than happy with this compromise.</p><h2 id="acknowledgments">Acknowledgments</h2><p>We would like to acknowledge the financial assistance of <a href="https://erudify.ch/about/">Erudify AG</a>, who graciously funded some of the documentation and development of the <code>io-streams</code> library. Many thanks are also due to Gabriel Gonzalez, Andrew Cowie, <a href="http://blog.johantibell.com/">Johan Tibell</a>, and <a href="https://github.com/basvandijk">Bas van Dijk</a> for their helpful discussions, contributions, and review.</p>
</div>2013-03-05T22:59:00+0100Announcing the first release of io-streams, a simple and easy-to-use library for doing streaming I/O in Haskell.