guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Fixing "stringly typed" data structures in Artanis (Was: Learning Guile


From: Thompson, David
Subject: Fixing "stringly typed" data structures in Artanis (Was: Learning Guile web. Stuck on returning an image.)
Date: Thu, 10 Dec 2015 17:02:52 -0500

[ Changing the subject for this little rant below ]

On Thu, Dec 10, 2015 at 2:44 PM, Martyn Smith
<address@hidden> wrote:

[snip]

> (get "/image"
>      (lambda (rc)
>        (let* ((port (open-file "s.jpg" "r"))
>                (bytes (get-bytevector-all port)))
>      (close-port port)
>      (response-emit bytes #:headers '((content-type image/jpg))))))
>
> (run #:port 1234)
>
>
> For my personal website, I pass in an id (ie "/image/{id}") which returns a
> record from the database, containing the location of the file in question...
> plus other things (tags, uploader, etc)  -- once working I stick it inside
> an image tag - job done!

I guess this is as good a time as any to voice a concern that I have
with Artanis before too many people depend on it and its not feasible
to change it.  In Scheme, we have the luxury of being able to easily
create embedded domain specific languages or otherwise take advantage
of s-expressions to avoid the tiring work of writing parsers and
interpreters for new languages.  However, Artanis features a URI
routing language written in strings, like "/user/:id".  This
particular string means: Match a URI beginning with "/user/", followed
by any string and associate it with the name "id".  Generally
speaking, this is a pattern matcher.  Unfortunately, unlike Guile's
built-in pattern matcher, these patterns must be string encoded and
cannot do more sophisticated matching techniques such as making sure
"id" is a string representation of an integer.  Doing this type of
string-based URI matching is the status quo in many web frameworks
written in Ruby, Python, etc., but in Scheme we have the opportunity
to do *much* better.  For an example that uses more proper Guile
Scheme idioms, take a look the source for the 'guix publish' tool in
GNU Guix. [0]  By viewing a URI as a list strings, we can represent
"/user/1" as the list ("image" "1").  From there, it's easy to use a
pattern matcher to match this route:

    (match uri (("user" id) (display-user-info id)))

>From there we can get more advanced and assert various things about
"id" in the match expression, as 'guix publish' does with its routes.

There are also security issues to think about when you use "stringly
typed" data.  It doesn't apply to this particular case, but working
with strings that are actually not strings (like HTML or SQL) opens
the door for injection attacks. [1] Fortunately, we can avoid such
issues entirely by choosing more appropriate data types.

I hope this has made some sense.  I think Artanis is a great project,
and I hope issues like this can be fixed so web developers looking at
Guile can truly see how much better it is in Lisp land.

- Dave

[0] http://git.savannah.gnu.org/cgit/guix.git/tree/guix/scripts/publish.scm#n309
[1] http://www.more-magic.net/posts/structurally-fixing-injection-bugs.html



reply via email to

[Prev in Thread] Current Thread [Next in Thread]