sharing constraints -> destructive substitution

I'm not sure if this builds because I couldn't build it against the version of URI in OPAM.  But I went ahead and gamely added in the bits of destructive substitution that I thought would be helpful.  I now understand why there is a request sub-module; that's because there are IO operations for Request.t's.  That seems reasonable enough, and the duplication isn't terrible, I think.  But there's no reason to have separate copies of the IO module in the different interfaces, and that's what this patch does.