<?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>asgaard</title>
  <description></description>
  <link>https://blog.asgaard.co.uk/2012/8</link>
  <lastBuildDate>Tue, 12 May 26 17:27:49 +0000</lastBuildDate>
  <language>en</language>
  <count>2</count>
  <offset>0</offset>
      <item>
    <title>Popularity is the hallmark of mediocrity</title>
    <link>https://blog.asgaard.co.uk/2012/08/26/popularity-is-the-hallmark-of-mediocrity</link>
    <pubDate>Sun, 26 Aug 12 10:31:09 +0000</pubDate>
    <guid>https://blog.asgaard.co.uk/2012/08/26/popularity-is-the-hallmark-of-mediocrity</guid>
    <description><![CDATA[
<p>
So said Dr. Niles Crane, quoting an unspecified &quot;great man&quot;.
<p>
I&#039;ve sunk a lot of hours into building various different programs. Partly because I enjoy it, partly due to necessity and partly because sometimes I genuinely believe I&#039;m creating something useful. The latter encompasses a bunch of my projects and with these I aim for painstakingly high quality because I want people to use them. I spend hours making sure code is written and formatted well, making sure unit test coverage is good, and ensuring that APIs are well documented, etc.
<p>
And then we have <a href='http://asgaard.co.uk/misc/loljs' target='_blank'>loljs</a>. loljs is my LOLCODE to JavaScript translator/interpreter. It&#039;s a proper translator with a recursive descent parse, not just a hideous regular expression thing, but it&#039;s still pretty rubbish. Probably its one saving grace in my eyes is that it correctly converts LOLCODE&#039;s prefix notation to JavaScript&#039;s infix notation for operators with arbitrary arity. I wrote it as a &quot;let&#039;s learn JavaScript project&[...]]]></description>
    <content:encoded><![CDATA[
<p>
So said Dr. Niles Crane, quoting an unspecified &quot;great man&quot;.
<p>
I&#039;ve sunk a lot of hours into building various different programs. Partly because I enjoy it, partly due to necessity and partly because sometimes I genuinely believe I&#039;m creating something useful. The latter encompasses a bunch of my projects and with these I aim for painstakingly high quality because I want people to use them. I spend hours making sure code is written and formatted well, making sure unit test coverage is good, and ensuring that APIs are well documented, etc.
<p>
And then we have <a href='http://asgaard.co.uk/misc/loljs' target='_blank'>loljs</a>. loljs is my LOLCODE to JavaScript translator/interpreter. It&#039;s a proper translator with a recursive descent parse, not just a hideous regular expression thing, but it&#039;s still pretty rubbish. Probably its one saving grace in my eyes is that it correctly converts LOLCODE&#039;s prefix notation to JavaScript&#039;s infix notation for operators with arbitrary arity. I wrote it as a &quot;let&#039;s learn JavaScript project&quot; in about two days. It&#039;s very rough, the internals are awful (it&#039;s pretty obvious I didn&#039;t know JavaScript) and it&#039;s not exactly easy to use.
<p>
And yet it&#039;s had literally thousands and thousands of visits. It&#039;s far and away the most successful project I&#039;ve done. Even taking into account professional projects, and I&#039;ve worked on some for a few big names, I think loljs is a pretty strong contendor in the popularity stakes.
<p>
It&#039;s recently been the subject of a <a href='http://www.youtube.com/watch?v=NkmJcgbXkJA&amp;feature=g-all-u' target='_blank'>&quot;learn to program&quot; video on a popular channel on YouTube</a> and according to my primitive stats, it&#039;s had six thousand views in the last 36 hours (not *all* from YouTube). Which is great. My web host is earning their monthly fee. I&#039;m very happy. I just wish you&#039;d all be so interested in the stuff I spent more time doing.]]></content:encoded>
  </item>
      <item>
    <title>HTTP 206 (Partial Content) For Flask/Python</title>
    <link>https://blog.asgaard.co.uk/2012/08/03/http-206-partial-content-for-flask-python</link>
    <pubDate>Fri, 03 Aug 12 11:32:53 +0000</pubDate>
    <guid>https://blog.asgaard.co.uk/2012/08/03/http-206-partial-content-for-flask-python</guid>
    <description><![CDATA[
<p>
Serving media files with HTTP 200 seems to make browsers act a bit strangely. Chrome refuses to fire onended events, and neither Chrome nor Firefox seems happy seeking through them. I am Not entirely sure for the reasons for this; I guess that they try to play the media before receiving all of it and can&#039;t guarantee they&#039;ll have downloaded the right chunk for seeking, while having no way of requesting it specifically. Who knows.
<p>
Here&#039;s a simple replacement to Flask&#039;s send_file that supports 206 partial content via byte ranges (and a function that adds the appropriate headers to all responses). It doesn&#039;t fully wrap send_file, if you care about all the other arguments and mirroring the exact behaviour, it needs a bit more work, but should suffice for 99% of uses.
<p>
[update 31/8: sorry there was a bug in this which caused strange things with certain Chrome versions, it&#039;s now been fixed]
<p>
<pre>import mimetypes
import os
import re

from flask import request, send_file, Response

@app.af</pre>[...]]]></description>
    <content:encoded><![CDATA[
<p>
Serving media files with HTTP 200 seems to make browsers act a bit strangely. Chrome refuses to fire onended events, and neither Chrome nor Firefox seems happy seeking through them. I am Not entirely sure for the reasons for this; I guess that they try to play the media before receiving all of it and can&#039;t guarantee they&#039;ll have downloaded the right chunk for seeking, while having no way of requesting it specifically. Who knows.
<p>
Here&#039;s a simple replacement to Flask&#039;s send_file that supports 206 partial content via byte ranges (and a function that adds the appropriate headers to all responses). It doesn&#039;t fully wrap send_file, if you care about all the other arguments and mirroring the exact behaviour, it needs a bit more work, but should suffice for 99% of uses.
<p>
[update 31/8: sorry there was a bug in this which caused strange things with certain Chrome versions, it&#039;s now been fixed]
<p>
<pre>import mimetypes
import os
import re

from flask import request, send_file, Response

@app.after_request
def after_request(response):
    response.headers.add('Accept-Ranges', 'bytes')
    return response


def send_file_partial(path):
    &quot;&quot;&quot; 
        Simple wrapper around send_file which handles HTTP 206 Partial Content
        (byte ranges)
        TODO: handle all send_file args, mirror send_file's error handling
        (if it has any)
    &quot;&quot;&quot;
    range_header = request.headers.get('Range', None)
    if not range_header: return send_file(path)
    
    size = os.path.getsize(path)    
    byte1, byte2 = 0, None
    
    m = re.search('(\d+)-(\d*)', range_header)
    g = m.groups()
    
    if g[0]: byte1 = int(g[0])
    if g[1]: byte2 = int(g[1])

    length = size - byte1
    if byte2 is not None:
        length = byte2 - byte1
    
    data = None
    with open(path, 'rb') as f:
        f.seek(byte1)
        data = f.read(length)

    rv = Response(data, 
        206,
        mimetype=mimetypes.guess_type(path)[0], 
        direct_passthrough=True)
    rv.headers.add('Content-Range', 'bytes {0}-{1}/{2}'.format(byte1, byte1 + length - 1, size))

    return rv</pre>
<br>
    ]]></content:encoded>
  </item>
  </channel>
</rss>