Chris Morgan

chrismorgan.info · Personal blog · on HN since 2013

Chris Morgan is a developer who writes about Rust, HTTP, and web server quirks, and runs a personal site with unusual experiments.

What HN saysCommenters enjoy his sassy server that rejects query strings, and point to his Rust ownership explainer as a useful companion to the official docs.
34HN people shared it
18linked it in comments
31stories submitted
881story points
3 months agolast shared
2013people per year2026

Most-shared posts

  1. 1
    I've Banned Query Strings
    8 people · 3 points · first shared 2026 · discussion on HN
  2. 2
  3. 3
    Rust ownership, the hard way
    4 people · 10 points · first shared 2015 · discussion on HN
  4. 4
    Why your first Rust FizzBuzz implementation may not work
    3 people · 184 points · first shared 2014 · 129 comments on HN
  5. 5
    Introducing Teepee: the next step for rust-http
    3 people · 43 points · first shared 2014 · 10 comments on HN
  6. 6
    Rust Ownership from the Hard Way
    3 people · 4 points · first shared 2021 · discussion on HN
  7. 7
  8. 8
    Font-Family Recommendations
    2 people · 4 points · first shared 2026 · discussion on HN
  9. 9
    Teepee design: header representation
    2 people · 4 points · first shared 2014 · discussion on HN
  10. 10
    Tween: a middleware library experiment
    2 people · 3 points · first shared 2016 · discussion on HN
  11. 11
    A few ways of specifying per-theme colours in only CSS
    2 people · 3 points · first shared 2026 · discussion on HN
  12. 12
    Atom is better than RSS, in ways that matter
    2 people · 1 points · first shared 2026 · discussion on HN
  13. 13
    Homepage
    2 people · first shared 2013
  14. 14
  15. 15
    Say “no” to import side‐effects in Python
    1 people · 148 points · first shared 2014 · 85 comments on HN

What HN people wrote when they linked it

xp84 · 2026-05-10
I love the hilarious output. He even coded in a special case for just a question mark without any params: https://chrismorgan.info/no-query-strings? Never have I seen such a sassy web server
varenc · 2026-05-10
great spot! I noticed that his server also doesn't accept URLs ending is a single `/`: https://chrismorgan.info/no-query-strings/ But instead of the banned query strings message, it just returns a very sassy not-a-404 page. Once again, this is violating a common convention, but there's nothing in the HTTP spec that requires treating these URLs the same. Similarly the site also 404s when you add extra slashes like https://chrismorgan.info///no-query-strings digression: I love trying "domain.com//" on various sites. Occasionally it'll trigger weird errors like a 502 or 500.
chrismorgan · 2026-01-14
https://chrismorgan.info/ Come back next week, and that should all be archived (preserving all content and links) and a new site in a completely different direction begun. A pure-CSS 3D space. Lots of handwriting. A synthesised pipe organ. And lots more, over time.
cratermoon · 2023-07-28
Pros: popular and commonly used; good for data science Cons: roughly the same paradigm and Javascript. weak/dynamic/duck typed, interpreted, garbage-collected. I'd recommend learning a language that departs from one or more of those. Maybe learn a statically-typed language, or a functional language. If you're up for a bit of a challenge, learn Rust. It's strongly typed, compiled, and definitely NOT garbage collected. It's possible to get a running program very quickly, but the learning curve steepens after that. If you do want to try Rust, here's some starting points - https://chrismorgan.info/blog/rust-fizzbuzz/ - https://stevedonovan.github.io/rust-gentle-intro/readme.html - https://www.lurklurk.org/effective-rust/intro.html - https://fasterthanli.me/articles/a-half-hour-to-learn-rust
steveklabnik · 2016-01-08
The official docs are https://doc.rust-lang.org/book/ownership.html and the following two sections. They explain the basics. I'm currently working on the next draft of the book, which will be more in-depth. http://chrismorgan.info/blog/rust-ownership-the-hard-way.html and http://codrspace.com/buntine/aha-understanding-lifetimes-in-rust/ are two blog posts that I can remember.
kibwen · 2014-10-01
I adore that someone like Armin is so delighted to use Rust. From what I've seen of Flask and his other Python libraries, the level of consideration that he devotes to API design is absolutely inspiring. At such an early stage in the language's history, I'm optimistic that his thoughtfulness in API design will become the baseline for the entire Rust ecosystem. In this vein, I'd also like to credit Chris Morgan's Teepee (http://chrismorgan.info/blog/introducing-teepee.html) and Sven Nilsen's Piston (https://github.com/PistonDevelopers) for devoting a great deal of energy to figuring out how best to structure Rust APIs that play to the strengths of the language. It's a process of discovery for all of us!
killercup · 2016-06-01
It's good to see new web-focused projects in Rust, I think it can be a really great language for this kind of thing. But to be honest, I'm looking forward to seeing what will be considered the go-to approach for Rust web applications _in a year_ or so. There is much experimentation going on right now, with cool little innovations here and there, but I have yet to see an approach that looks really new and Rust-y to me. For example: Rust's type system certainly has some nice properties to track dependencies between middlewares[^1] but I'm not convinced middlewares are even the best approach possible here. Also, it will be interesting how a framework based on async IO will look and what tricks/syntactic sugar/macros will be employed to keep boilerplate code down. This is a pretty big order, of course: While I enjoy using small libraries, a well designed web framework requires a lot of organisational effort for all the small pieces to fit together nicely. I think most of the 'small pieces' are already there or at least well under way, by the way. For example: The async (mio) branch of hyper looks pretty solid for HTTP1/2, the Diesel ORM is fantastic (and will, according to creator Sean Griffin, soon hit 1.0), and handling JSON will only get better with future versions of serde. [^1]: As recently discussed in https://chrismorgan.info/blog/tween.html and some other posts concerning the use of sessions types in Rust.
dang · 2026-05-09
Since the original source hadn't had a discussion on HN yet, I've put that link (https://chrismorgan.info/no-query-strings) at the top and moved the response link (https://susam.net/no-query-strings.html) to the toptext. Both are good but it seems fair to give priority to the original!
moritzwarhier · 2026-05-08
This is cool and creative! It uses 4xx, but not just 400 :) https://chrismorgan.info/no-query-strings?why=unknown
plondon514 · 2021-10-11
This interactive tutorial is an adaptation of Chris Morgan's blog post which can be found here: https://chrismorgan.info/blog/rust-fizzbuzz/
iamdanfox · 2015-01-03
Apparently the Rust compiler produces a slightly different branch-free FizzBuzz[1] involving this delightful snippet: static OUT: &'static [u8] = b"\ 1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n\ 16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n\ 31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n\ 46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n\ 61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n\ 76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n\ 91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz\n"; ... 1: http://chrismorgan.info/blog/rust-fizzbuzz.html
tmzt · 2014-09-16
There are already a number of libraries and frameworks that implement an HTTP setver in Rust, though things seem to be coalescing around Teepee. http://chrismorgan.info/blog/introducing-teepee.html#main There are few REST api libraries as well.
jampekka · 2026-05-09
"You could argue that I’m abusing 414 URI Too Long. I respond that it’s funnier this way. Other options I considered were: 400 Bad Request, the generic client error code, which is correct but boring; 402 Payment Required, and honestly if you want to pay me to make a particular URL with query string work, I’m open to it; 404 Not Found, but it’s too likely to have side effects, and it doesn’t convey the idea that the request was malformed, which is what I’m going for; and 303 See Other with no Location header, which is extremely uncommon these days but legitimate. Or at least it was in RFC 2616 (“The different URI SHOULD be given by the Location field in the response”), but it was reworded in 7231 and 9110 in a way that assumes the presence of a Location header (“… as indicated by a URI in the Location header field”), while 301, 302, 307 and 308 say “the server SHOULD generate a Location header field”. Well, I reckon See Other with no Location header is fair enough. But URI Too Long was funnier." https://chrismorgan.info/no-query-strings?foo
susam · 2026-05-09
I'll start with the clarification that the moderators have changed the URL of the original post from <https://susam.net/no-query-strings.html> to <https://chrismorgan.info/no-query-strings>. Hopefully, this will prevent any confusion about why we are discussing random walks in a post about query strings. Now let me answer your question. > Is it not a random walk? Might sound pedantic but if there is graph structure I am interested. The network is a directed graph. Every Wander Console declares some other consoles as its neighbours. So if we call the network graph X, then the set of vertices is: V(X) = the set of all URLs that point to Wander Consoles and the set of edges is: E(X) = {(u, v) in V(X) : u declares v as its neighbour} The traversal between consoles is not strictly a random walk. If I had to give it a name, I would call it randomised graph exploration with frontier expansion. On each click of the 'Wander' button, the tool picks one console at random from the set of discovered consoles and visits that console. It then fetches the neighbours declared by that console and adds any newly discovered consoles to the set. The difference from a random walk is that the next console is not chosen from the neighbours of the last visited console. It is chosen from the whole set of consoles discovered so far. In other words, each click expands the known part of the graph, but the console used for that expansion is selected randomly from all discovered…
amadeuspagel · 2021-08-24
> And possibly the autodiscovery needs tweaking too, as I observe it not finding the feed on my site https://chrismorgan.info/, which is properly specified; my first guess is that it’s not coping with the type=application/atom+xml attribute. I fixed that: https://mergefeed.net/Untitled?urls=https://chrismorgan.info/ > In related news, MergeFeed is currently vulnerable to injection attacks because it mishandles Atom titles that are specified as text. If you specify a title as HTML or XHTML, it filters out a <script> element properly (good! and while retaining inline formatting too!), but if you specify a title as text, it doesn’t escape the HTML (which is what it should do) or filter it (which would have been wrong but would at least have closed the security vulnerability). Proof of concept: https://mergefeed.net/-?urls=https://temp.chrismorgan.info/xss.atom I fixed that too. But for now I wasn't able to fix it without also removing formatting. I might be able to figure out how to keep formatting without allowing XSS attacks later, but I'm not sure that's even a good idea. It's kind of a link aggregator and link aggregators generally don't allow formatting. You don't want people to try to gain attention that way, leading to an arms race.
byuu · 2014-11-28
Pretty much all of it. For example, let's take http://chrismorgan.info/blog/teepee-design-header-representation.html impl<'a> AnyRefExt<'a> for &'a Header { #[inline] fn as_ref<T: 'static>(self) -> Option<&'a T> { trait UncheckedAnyRefExt<'a> { unsafe fn as_ref_unchecked<T: 'static>(self) -> &'a T; } //I am guessing the second line is special because Rust can't deduce "to" should be a TraitObject type? let raw = require_single_field!(raw); let to: TraitObject = transmute_copy(&self); //is this adding header and 'static together? pub trait HeaderMarker<OutputType: Header + 'static> { //I have zero clue what this is doing //I can't even fathom a guess match *self { Past => write!(f.buf, "0"), ExpiresDate(ref tm) => tm.fmt_header(f), } //so _raw is a reference to a vector of bytes inside [] and it might possibly return whatever a box is of headers? fn parse_header(_raw: &[Vec<u8>]) -> Option<Box<Header>> { //is there really a language keyword called macro_rules! ? macro_rules! impl_header_from_fromstr { //what in the world is ($ty:ty)? ($ty:ty) => (impl Header for $ty { fn parse_header(raw: &[Vec<u8>]) -> Option<$ty> { //who thought "h.is::<H>()" was a good way to test a type? Why not "h.is(H)?" Why the => ? //what is this even returning? a tuple of false and None? Typed(ref h) if h.is::<H>() => { (false, None) …
DonHopkins · 2024-08-19
How it works and how it should be used are different. Say “no” to import side‐effects in Python: https://news.ycombinator.com/item?id=7536246 https://chrismorgan.info/blog/say-no-to-import-side-effects-in-python >I must be able to import your module— any module— at any time without anything breaking. Or even the beneficial side effect of some other module running 10% faster. ;) What side-effects, if any, are okay when importing a python module? https://softwareengineering.stackexchange.com/questions/454069/what-si… >Q: Is this a better design pattern or does it just kick the issue down the road? >A: Kicking the issue down the road is the basic idea of the "functional core, imperative shell" design pattern. Functional Core, Imperative Shell (2012): https://news.ycombinator.com/item?id=34860164 https://www.destroyallsoftware.com/screencasts/catalog/functional-core…

Keyboard shortcuts

/Search
j kNext / previous blog
EnterOpen selected blog
vVisit the blog site
fFollow / unfollow
lSwitch grid / list view
dSwitch dark mode
g hHome
g pTop posts
g tTopics
g fFollowing
g lLiked
g yHistory
g qFAQ
EscBack / close