News for hackers. Stuff that matters.
Re:Scala – 1 Star – Would Not Program Again by chrismorgan on Sunday December 01, 2013 @07:46PM (#6830384)
The section on HTTP headers and typing is a little concerning to me. I've been making rust-http recently and (before I was aware of Spray) I felt strongly about the typing. So, I'd like to discuss this. Am I wrong after all? Here clearly is someone that disagrees with me. I think I should probably write up a long blog post on the topic explaining my reasoning and so forth.

rust-http is, at present at least, rejecting the standard practice of stringly typed headers and is using strongly typed headers.

> ... and even types for every ‘known’ HTTP header.

> The known HTTP header part was particularly ridiculous. HTTP headers are defined as simple key/value pairs. You’re supposed to be allowed to add arbitrary headers. You’re not supposed to be constrained by the framework you’re using not having any support for CORS yet.

He has taken a strong position against this strong typing; I take a similarly strong position for such strong typing.

Yes, HTTP headers are defined as simple key/value pairs. But headers are not text; they are data. XML is defined as text. Should we use regular expressions to work with it? (True, it also has the DOM defined. But HTTP headers also have a grammar defined—it just happens to include the admissibility of extension headers.)

HTTP is a serialisation format for messages; messages made up of computer-readable data, not text.

I wrote a handful of paragraphs about this subject at https://github.com/chris-morgan/rust-http/issues/1 where using a map instead of typed headers was suggested.

As I also note there, I would not attempt such a scheme in a language like Python (my primary language for some years) because its type system is not well adjusted to something like this; I am certain it would cause many problems and feel it likely it would cause more than it solved. But in a language with a solid type system capable of expressing these things, taking advantage of it should lead to a faster, more correct program.

In the end, I believe strongly typed headers are a good thing to have (it will actually make most code distinctly nicer—e.g. ``response.headers.date = Some(now())`` instead of ``response.headers.set("Date", now().to_http_header())``). The implementation of the scheme in rust-http is certainly not perfect yet; I'm not happy with it at present; I'm expecting to turn the extension headers into a trait object, and I've even considered crazy ideas like allowing users of the library to make their own header collection (request.headers and response.headers) types—that would allow custom headers to be made first-class citizens but could lead to compatibility problems.

Still, I don't want to make something that I believe should be the best HTTP library around and find that people hate to use it. What do you think about this header matter?

Re:Scala – 1 Star – Would Not Program Again by ubernostrum on Sunday December 01, 2013 @10:54PM (#6831449)
My main concern is the last sentence of the section you quote. There's tension between headers which are well-known and standardized (either formally or through de-facto wide use), and so are amenable to being properly modelled, and headers which are not well-known or which may not even exist yet. Hence, I think, his comment about CORS.

And I'm not sure there's a good solution. The obvious approach, as you already know, is to separate headers into two groups: one group is "properly" handled, and the other group gets tossed into an "other" bucket of key/value string pairs. But it's going to be awfully tempting over time to have "proper" support for the most common non-RFC2616 headers, especially those which have widely-accepted standards of their own.

But that's a bit messy and much less than ideal, as you've also discovered. And I don't know of another way to approach the problem that still lets you have the stuff you want from the type system, and doesn't cut people off the minute they start using extension headers your library doesn't know about.

And that's without getting into all the completely stupid things it's technically legal to do in an HTTP header, and the even more stupid things that aren't legal but that people do anyway. My usual torture test of an HTTP library these days runs through things like non-ASCII content in header values (legal if properly encoded, and not everything in the wild properly encodes), looking to see how large a value a library will accept, whether it will let me throw newlines into headers, etc. etc.

Re:Scala – 1 Star – Would Not Program Again by dancapo on Tuesday December 03, 2013 @11:49PM (#6845095)
The thing is, support for arbitrary header is there: RawHeader, defined as a pair of header name and header value strings.
Re:Scala – 1 Star – Would Not Program Again by bmurphy1976 on Sunday December 01, 2013 @11:01PM (#6831480)
Strongly typed headers are great, but for the love of God please give us a back door. And I don't mean just a dictionary for every "unknown" header, but we should be able to override every "known" header as well.

I'll give you a real-world example. Mono. HttpWebRequest used to store the Content-Size value as an int32. What about files larger than 4gb? Oops...

That was a big problem for us. Thankfully Mono is open source, we were able to peruse the code and come up with some magic incantations using reflection to work around the fact that the framework libraries would not allow us to set the Content-Size header without going through the int32 property.

Now, normally you would file that as a bug, however, it (A) took years for a version of mono to be released with that fixed this and (B) could easily have been some misunderstanding in the implementation of the HTTP spec that was overlooked. You're implementing a spec right now. Can you guarantee that the your implementation is 100% correct? Can you guarantee that the spec is 100% correct? Can you guarantee that the spec is implemented 100% correct everywhere?

No, you can't.

So, don't limit me. Help me, but do not prevent me from doing what I need to in order to do my job.

Re:Scala – 1 Star – Would Not Program Again by bmurphy1976 on Sunday December 01, 2013 @11:16PM (#6831550)
I have another good example. Please see this thread I posted to the Go mailing list a few months ago:

https://groups.google.com/forum/#!searchin/golang-nuts/s3/go...

The short summary is that Amazon S3 does not behave like a normal web server and expects HTTP path's to be "url encoded". S3 is pretty obviously something you would want to interoperate with. Go's http client (which isn't very strict at all) causes friction here.

Re:Scala – 1 Star – Would Not Program Again by steilpass on Monday December 02, 2013 @05:18AM (#6832845)
Too bad it didn't get very much attention on the mailing list.
Re:Scala – 1 Star – Would Not Program Again by timtadh on Sunday December 01, 2013 @08:31PM (#6830616)
The way I look at type systems is they are an automatic proof system for programs. So you must ask yourself what are you proving with your type system? I looked at your write up on the github issue and from what I see you are moving some checking into compile time. However, when it comes to "parsing problems" (like: HTTP, XML, command line args, etc...) there isn't much to move. This is because the data doesn't yet exist that the proof operates on. So it really can only check the plumbing after the parsing - which often isn't that much.

In the past when I have used such libraries they have been a pain - especially for loose formats like HTTP headers. Type system come with a cost, you need to carefully consider the burden you are placing on the programmer to see if the benefits out way the cost.

Re:Scala – 1 Star – Would Not Program Again by nardi on Monday December 02, 2013 @01:33AM (#6832114)
This tactic seems to betray a certain amount of naivety with regard to how closely most real-world HTTP implementations follow the specifications. (Hint: they don't follow the specifications.)

Remember Postel's law: "Be conservative in what you do, be liberal in what you accept from others."

Unfortunately, you will have to return URLs to your users that are invalid. You will have to parse slightly malformed dates. Your clients will expect to be able to pass through malformed values from bad endpoints and not introduce a point of failure in your library. (Do you know about the "Cneonction: close" trick, for instance? All real-world proxies do all sorts of batshit-crazy HTTP header munging.)

If your library can't accept and pass through arbitrary strings for arbitrary headers, and return them to users, and then accept them back again, then it is unlikely to be successful in any sufficiently complex and robust HTTP service.

Re:Scala – 1 Star – Would Not Program Again by axiak on Sunday December 01, 2013 @07:58PM (#6830442)
IMHO, libraries like this should always have an easy "out", where the default is strongly typed, but the user of the library can explicitly escape the known behavior if need be.

As a (albeit poor example), I once inherited a click tracking system that uses Java Jersey. The standard response object has a .redirect(URI uri) method. Unfortunately, many "URI"s we receive from the world are not actually value, and the java URI object refuses to build URI objects from the string. Fortunately, one can simply call .setHeader(String, String) and be done with it.

Re:Scala – 1 Star – Would Not Program Again by chrismorgan on Sunday December 01, 2013 @08:17PM (#6830541)
At present, in rust-http, invalid values will be dropped; that will be changing so that you can retrieve a bad header value (https://github.com/chris-morgan/rust-http/issues/27). Writing invalid HTTP, on the other hand, is something that I'm in two minds about. You shouldn't be allowed to do it, but it may be necessary somewhere along the way. At present, you can write invalid headers through the use of the extension headers—`response.headers.extension.set(~"Date", ~"invalid")`, for example. I certainly don't want to advertise it broadly, but I'm thinking guaranteeing that that will always work is perhaps the best plan.
Re:Scala – 1 Star – Would Not Program Again by zaphar on Sunday December 01, 2013 @09:16PM (#6830951)
The author isn't wanting to write invalid headers. He's wanting to write perfectly valid headers that the framework he's using didn't allow him to write.

When the framework treats a a valid http header as invalid the framework is probably using the wrong abstraction for http headers.

Re:Scala – 1 Star – Would Not Program Again by ethzero on Sunday December 01, 2013 @09:36PM (#6831081)
Spray allows you to define custom (even invalid) headers, all you have to do is subclass HttpHeader. I'm sure the author knew this, but it's not obvious from his criticism.
Re:Scala – 1 Star – Would Not Program Again by timtadh on Sunday December 01, 2013 @08:36PM (#6830648)
You should always allow the user to get the raw HTTP request. Sometimes things just get funky and you need to drop down to that level. Abstraction is nice except when it isn't, if you understand my meaning.
Re:Scala – 1 Star – Would Not Program Again by jamesaguilar on Sunday December 01, 2013 @09:40PM (#6831098)
> not text, they are data

You can be both . . .

IMO, all the fields need to have a Printable and Readable trait (or whatever Rust's version of those are). If you want to do special things for certain fields to make them easier to work with, I think that's cool too. But if you force people not to treat headers as text, I think you're going to have a problem.

Re:Scala – 1 Star – Would Not Program Again by renshaw on Sunday December 01, 2013 @10:14PM (#6831259)
I'm with you, in favor of strongly typed headers. Working with strings can be very error-prone; you might not catch typo bugs until your system is in production and handling some rare case for which failure is expensive.

It seems to me that, in the worst case, the downside of your current scheme is an extra field dereference, as in `request.headers.extensions.get("crazyNewField")` instead of `request.headers.get("crazyNewField")`. I think that cost is easily outweighed by the benefits.

Re:Scala – 1 Star – Would Not Program Again by halostatue on Monday December 02, 2013 @12:38AM (#6831900)
By and large, follow Postel’s law on this (http://en.wikipedia.org/wiki/Robustness_principle). As others have also said, though, make it not-too-hard to do things that your type system would otherwise restrict, because if I have to interact with a misbehaving server (including to the point where I have to send what would otherwise be invalid header data), then your strictness would make it too hard to do so.
Re:Scala – 1 Star – Would Not Program Again by EpicEng on Sunday December 01, 2013 @09:56PM (#6831176)
But what practical problem is such a scheme actually solving? If I write

    response["headre"] = ...
I have a bug, sure, but an obvious bug that will be fixed very quickly. With this type system I am now limited in an annoying way. I don't get it.
Re:Scala – 1 Star – Would Not Program Again by pcwalton on Monday December 02, 2013 @12:24AM (#6831831)
> I have a bug, sure, but an obvious bug that will be fixed very quickly.

People say the same thing about null pointer exceptions, but null pointer exceptions are a huge problem in practice. Every bug is "obvious" in retrospect.

Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @01:19PM (#6835373)
No, this is not the same as a null pointer. Null pointers are typically much more sneaky, this line means the header will not be written and the error is right in your face.

I do understand the desire to prevent these sorts of errors at the language level, but not at the cost of functionality. I don't agree with this one, but I do (for example) appreciate libraries such as the STL which (hopefully) prevent that pointer issue you brought up (and more). The STL doesn't (often) force me to work around silly limitations though.

Does this library provide for creating arbitrary headers in some other fashion? If not, why?

Re:Scala – 1 Star – Would Not Program Again by asdf1234 on Monday December 02, 2013 @01:12AM (#6832057)
And yet bugs like this make it into production systems all the time. Several Rails security bugs have been almost as trivial and just as avoidable.
Re:Scala – 1 Star – Would Not Program Again by peq on Monday December 02, 2013 @05:22AM (#6832862)
For me, a big benefit is the tooling support. If the API is statically typed, I can easily find the headers I am able to set using my IDE. And for setting the date I don't have to check the http spec for which syntax I have to use for the date.
Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @01:34PM (#6835467)
That's not a bad point, I'm just not sure I am willing to give up functionality for tooling. The end goal here is a program that people can use to get things done, not awesome IDE integration.
Re:Scala – 1 Star – Would Not Program Again by asdasf on Monday December 02, 2013 @10:29AM (#6834197)
>I have a bug, sure, but an obvious bug that will be fixed very quickly

I love that there are people who say things like this totally seriously.

Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @01:29PM (#6835436)
I'm not sure what you've done to make you feel like being condescending is something you have earned, but please feel free to share your body of work.

I've worked on very large, complex, mission critical systems my entire career. Medical devices mostly. If you're not catching these sorts of errors early then you aren't modeling and testing your software correctly (or at all). All of the objects in the world aren't going to prevent you from writing bugs and crappy code. OO is no panacea and we've known that for quite some time now. I don't want to use a library which is limiting because it thinks it is doing me a favor.

Re:Scala – 1 Star – Would Not Program Again by the_af on Monday December 02, 2013 @03:00PM (#6836094)
Why not use every tool at your disposal that can catch bugs early? Static typing does that. Sure, you can catch bugs later with testing, but why not take advantage of automated tools (i.e. the compiler)? That's one less test you have to write.
Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @09:34PM (#6838120)
The original post was decrying the limitations of a specific library. If you can implement the map in a better way while still allowing the freedom I/we need then fine. If you can't then get out of my way and hand me the map.
Re:Scala – 1 Star – Would Not Program Again by asdasf on Monday December 02, 2013 @02:01PM (#6835658)
What an odd response. I haven't done any OO programming in nearly a decade, and I would not consider doing it ever again. I don't know where you got the idea that OO has anything to do with this. I do catch these sorts of errors early on, because they are type errors, and thus the compiler catches them. That is very much the point. The fact that you think you are infallible and can write 100% perfect test coverage, while thinking I am being condescending is pretty hilarious.
Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @02:31PM (#6835897)
Not odd at all; you were being condescending, trying to paint me as someone who isn't as good a programmer as you are. Maybe I'm not, but I've written some very robust systems code in my career, so don't be so quick to write people off.

I don't think I'm infallible (straw man much?), but I do think that dead simple errors such as this would be caught by any amount of actual testing. That said, I wouldn't be against a better design. Why doesn't this library provide a way to add arbitrary headers? Oh, right, that would still involve using a string. Gasp, no, that shouldn't be allowed. We have to protect the poor users of our library. Yeesh.

You can't always protect a programmer from themselves while still allowing the flexibility/power needed to get shit done. I'd rather use the map than some overly architected and frustrating library. I have a problem with abstractions that get in my way.

Re:Scala – 1 Star – Would Not Program Again by asdasf on Monday December 02, 2013 @05:12PM (#6836946)
No, you interpreted it as condescending. Just because I enjoy unbridled optimism does not mean I am condescending.

You are suggesting that you are infallible, as the "dead simple errors" you refer to get out into production systems every single day. More than one serious security hole in rails has been due to very similar problems. You are very much implying that you are a better programmer than the entire rails team. And virtually everyone else, as examples of these kinds of bugs are everywhere.

And finally, crying straw man while presenting a straw man is poor form. If a particular library has a deficiency, that's unfortunate. But it has absolutely nothing to do with type safety. Haskell for example is more type safe, and it has two http client libraries, both of which provide safety while also allowing arbitrary headers (and methods, etc).

Re:Scala – 1 Star – Would Not Program Again by EpicEng on Monday December 02, 2013 @09:38PM (#6838136)
Who cares about your super awesome Haskell library? You have meandered our of context. My response was in response to a defense of this particular implementation. If your abstraction sucks then I don't want it as it will cause me more headache than it is worth. That's the point.

EDIT: Eh... looking back at my original comment I don't think I got that across at all. It reads as more of a rant against a typed system in general, which is not what I intended.

Re:Scala – 1 Star – Would Not Program Again by Myrmornis on Tuesday December 03, 2013 @04:19AM (#6839367)

  I love that there are people who say things like this totally seriously.
No, it was condescending.
Re:Scala – 1 Star – Would Not Program Again by defen on Sunday December 01, 2013 @08:14PM (#6830527)
What does your library do if someone sends invalid data? For example what if the date header is not a valid HTTP-formatted date?
Re:Scala – 1 Star – Would Not Program Again by hrjet on Monday December 02, 2013 @12:56AM (#6831985)
Although I appreciate this discussion, both the OP and you are off-topic. This is a library design issue, not a language level issue.

If people like OP are dissing a language because they don't like a particular library's API, they have very strange expectations from the language. And if you are worried about this section of users, then I would say in order to make good use of your time, it is best to ignore them.

Re:Scala – 1 Star – Would Not Program Again by PeterisP on Monday December 02, 2013 @06:02AM (#6832990)
For all practical purposes, you're never comparing just the core language, but the language+libraries for common tasks (no matter if it ships 'batteries included' or not)+the whole ecosystem and community of library developers.

If it's hard to do X in your language, but easy in other languages - then that's a weakness for your language, despite that 90% of X's will be outside of the language core.

And even 'optional extras' in your language can be weaknesses instead of features - if they are often used by library makers for less readable/maintainable code than the other options.

Re:Scala – 1 Star – Would Not Program Again by est on Sunday December 01, 2013 @10:52PM (#6831436)
> I take a similarly strong position for such strong typing.

Why not add a weak checking for k-v strings? Something like during compile time:

    if not k in LIST_OF_WELLKNOWNS
        warn('Bad header maybe?')
You don't have to use types to check this.
Re:Scala – 1 Star – Would Not Program Again by lmm on Monday December 02, 2013 @04:07AM (#6832606)
You don't have to use types, but if you do then the type system guarantees your checks are exhaustive, which is more effective than manually checking you've covered all the paths.

I really like the spray way. You can add a custom/nonstandard header by using RawHeader(key, value), but most of the time you use e.g. Headers.ContentType(MediaTypes.`application/json`), and it just completely eliminates a class of trivial but annoying bugs.