http headers are case insensitive

147 views
Skip to first unread message

bblfish

unread,
Oct 10, 2011, 9:46:09 AM10/10/11
to dispatc...@googlegroups.com
In Handerlers.scala the way of accessing the headers is with  

def >:> [T] (block: IMap[String, Set[String]] => T) = 
    Handler(request, (_, res, _) => 
      block((IMap[String, Set[String]]().withDefaultValue(Set()) /: res.getAllHeaders) { 
        (m, h) => m + (h.getName -> (m(h.getName) + h.getValue))
      } )
    )

In http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.5 it is written "Field names are case-insensitive."

It seems to me that the IMap returned should somehow normalise the headers and do the same for the queries so that code does not end up loosing information.

Erik Peterson

unread,
Oct 10, 2011, 1:14:12 PM10/10/11
to dispatc...@googlegroups.com
Agreed. But how do you construct a Scala map with case-insensitive string keys?

The following shows a Java TreeMap like what we would need. http://bytes.com/topic/java/answers/617110-case-insensitive-collections-sets-maps-etc

Map<String, Objectmap =
    new TreeMap<String,Object>(String.CASE_INSENSITIVE_ORD ER);

Henry Story

unread,
Oct 10, 2011, 1:21:18 PM10/10/11
to dispatc...@googlegroups.com
The other solution would be to add a function to lowercase every string on entry into the map, and to lowercase
every query string too.

Henry

Social Web Architect
http://bblfish.net/

Erik Peterson

unread,
Oct 10, 2011, 1:43:15 PM10/10/11
to dispatc...@googlegroups.com
The problem with that approach is that you lose the original request string--which may be important in some cases. (no pun intended ;-)

Henry Story

unread,
Oct 10, 2011, 2:37:24 PM10/10/11
to dispatc...@googlegroups.com

On 10 Oct 2011, at 19:43, Erik Peterson wrote:

The problem with that approach is that you lose the original request string--which may be important in some cases. (no pun intended ;-)

makes sense.

Nathan Hamblen

unread,
Oct 10, 2011, 4:35:14 PM10/10/11
to dispatc...@googlegroups.com
On 10/10/2011 02:37 PM, Henry Story wrote:
>
> On 10 Oct 2011, at 19:43, Erik Peterson wrote:
>
>> The problem with that approach is that you lose the original request
>> string--which may be important in some cases. (no pun intended ;-)
>
> makes sense.
>

I wonder if we should take this opportunity to provide a more user
friendly way to access headers, with a new interface. People seem to
find the required use of >+ and >+> pretty confusing, and awkward even
after they understand how it works.

Nathan

Henry Story

unread,
Oct 10, 2011, 4:47:58 PM10/10/11
to dispatc...@googlegroups.com

yes, it is quite complicated. I got it to function right now, after quite a bit of work though. Part of the problem was IntelliJ perhaps not getting the syntax right. So I had to write out the types carefully. Here's my first use:

def get() = {
// note we prefer rdf/xml and turtle over html, as html does not always contain rdfa, and we prefer those over n3,
// as we don't have a full n3 parser. Better would be to have a list of available parsers for whatever rdf framework is
// installed (some claim to do n3 when they only really do turtle)
// we can't currently accept */* as we don't have GRDDL implemented
val request = url(u.toString) <:< Map("Accept"->
"application/rdf+xml,text/turtle,application/xhtml+xml;q=0.8,text/html;q=0.7,text/n3;q=0.6")

//we need to tell the model about the content type
val handler: Handler[Validation[Throwable, Model]] = request.>+>[Validation[Throwable, Model]](res => {
res >:> { headers =>
val encoding = headers("Content-Type").headOption match {
case Some(mime) => RDFEncoding(mime)
case None => RDFXML // it would be better to try to do a bit of guessing in this case by looking at content
}
val loc = headers("Content-Location").headOption match {
case Some(loc) => new URL(u,loc)
case None => new URL(u.getProtocol,u.getAuthority,u.getPort,u.getPath)
}
res>>{ in=>modelFromInputStream(in,loc.toString,encoding) }

}
})
http(handler)

}

What I wonder is if there is no way to somehow make it work with the Unfiltered header objects. Somehow it seems one feels like the pattern matching on headers should work here too...

Henry

>
> Nathan

Nathan Hamblen

unread,
Oct 10, 2011, 5:44:17 PM10/10/11
to dispatc...@googlegroups.com
On 10/10/2011 04:47 PM, Henry Story wrote:
> On 10 Oct 2011, at 22:35, Nathan Hamblen wrote:
>
>
> What I wonder is if there is no way to somehow make it work with the Unfiltered header objects. Somehow it seems one feels like the pattern matching on headers should work here too...

That's a neat idea. It would be tempting (and tricky) to share the code,
but there is not actually that much to share because Unfiltered is
concerned with extracting request headers. For response headers it has
response functions, which won't do us any good. But we could certainly
copy the idea and supply a slew of response header extractors.

Nathan

Peter Robinett

unread,
Oct 11, 2011, 8:09:31 AM10/11/11
to dispatc...@googlegroups.com
Anything that makes it easier to access response status codes and headers is a major win in my book, as I'm all out the conditional HTTP requests. =)

Peter

bblfish

unread,
Jul 5, 2012, 4:39:30 AM7/5/12
to dispatc...@googlegroups.com


On Monday, 10 October 2011 19:43:15 UTC+2, Erik Peterson wrote:
The problem with that approach is that you lose the original request string--which may be important in some cases. (no pun intended ;-)

Funny, I just found this thread again (9 months later) because I came across this problem. I need the case insensitive match on headers, but  I want the
original headers too, because I want to write a Proxy service that will pass the original request on to another service, and having the original headers is
quite important, as other services may have not correctly implemented case-insensitivity...

I wonder indeed if the solution you mentioned 

Map<String, Objectmap =
    new TreeMap<String,Object>(String.CASE_INSENSITIVE_ORD ER);


is noticeably slower than HashSet for hashes the size of headers < 100 where ln(100) = 4.6  ln(10)=2.3 

seemed to have a solution using Proxy that could be used with HashSet

Reply all
Reply to author
Forward
0 new messages