Hi, a user pointed out that a rewrite rule which adds quotes around a variable 
causes the variable substution not to happen, e.g.

{
  "query": { "key": "\":arg\"" }
}

I had to stare a long time at couch_httpd_rewrite to see why that was the case. 
 I found the replace_var/3 function to be awesomely gnarly:

https://github.com/apache/couchdb/blob/trunk/src/couchdb/couch_httpd_rewrite.erl#L256

There are so many bad things going on in this function:

1) I'm pretty sure the final clause of the case statement can never be reached. 
 Calls to replace_var/3 are guarded by is_list/1 and is_binary/1 guards on the 
Value, so we're always going to hit one of the previous clauses.

2) Putting that aside for a moment, what was the point of the inner case 
statement?  Are we writing code that distinguishes between 
lists:flatten(?JSON_ENCODE(Value)) and iolist_to_binary(?JSON_ENCODE(Value)) ?  
I hope not.

3) I found the is_list(Value) clause to be almost a copy of the outer clause, 
but not quite.  It looks to me like that clause is being used to handle the 
situation like "query":{"key": [":a",":b"]}, but I believe there are better 
ways to do that.

4) Sure enough, the rewriter requires an exact match on <<":", Var/binary>> in 
order to do the substitution, and it does not JSON encode the result, even if 
the query key is something that requires a JSON-encoded value.  In effect, I 
see no way to use the rewriter to set the value of key to a string.

I started to refactor this function a bit and ended up with 
http://friendpaste.com/ZzyuR2gM0JVdDmgGhjXbI.  It still doesn't address the 
root problem of the JSON-encoding requirement for key/startkey/endkey/etc., but 
it's a start.  I've never had occasion to look closely at the rewriter before, 
so someone else should check to make sure I'm not way out in left field here.

Adam

Reply via email to