rewrite performs the rewrites on r using repl, which should have been obtained from r, but is passed in for efficiency. It returns true if any changes were made to r.
(r *http.Request, repl *caddy.Replacer)
| 156 | // have been obtained from r, but is passed in for efficiency. |
| 157 | // It returns true if any changes were made to r. |
| 158 | func (rewr Rewrite) Rewrite(r *http.Request, repl *caddy.Replacer) bool { |
| 159 | oldMethod := r.Method |
| 160 | oldURI := r.RequestURI |
| 161 | |
| 162 | // method |
| 163 | if rewr.Method != "" { |
| 164 | r.Method = strings.ToUpper(repl.ReplaceAll(rewr.Method, "")) |
| 165 | } |
| 166 | |
| 167 | // uri (path, query string and... fragment, because why not) |
| 168 | if uri := rewr.URI; uri != "" { |
| 169 | // find the bounds of each part of the URI that exist |
| 170 | pathStart, qsStart, fragStart := -1, -1, -1 |
| 171 | pathEnd, qsEnd := -1, -1 |
| 172 | loop: |
| 173 | for i, ch := range uri { |
| 174 | switch { |
| 175 | case ch == '?' && qsStart < 0: |
| 176 | pathEnd, qsStart = i, i+1 |
| 177 | case ch == '#' && fragStart < 0: // everything after fragment is fragment (very clear in RFC 3986 section 4.2) |
| 178 | if qsStart < 0 { |
| 179 | pathEnd = i |
| 180 | } else { |
| 181 | qsEnd = i |
| 182 | } |
| 183 | fragStart = i + 1 |
| 184 | break loop |
| 185 | case pathStart < 0 && qsStart < 0: |
| 186 | pathStart = i |
| 187 | } |
| 188 | } |
| 189 | if pathStart >= 0 && pathEnd < 0 { |
| 190 | pathEnd = len(uri) |
| 191 | } |
| 192 | if qsStart >= 0 && qsEnd < 0 { |
| 193 | qsEnd = len(uri) |
| 194 | } |
| 195 | |
| 196 | // isolate the three main components of the URI |
| 197 | var path, query, frag string |
| 198 | if pathStart > -1 { |
| 199 | path = uri[pathStart:pathEnd] |
| 200 | } |
| 201 | if qsStart > -1 { |
| 202 | query = uri[qsStart:qsEnd] |
| 203 | } |
| 204 | if fragStart > -1 { |
| 205 | frag = uri[fragStart:] |
| 206 | } |
| 207 | |
| 208 | // build components which are specified, and store them |
| 209 | // in a temporary variable so that they all read the |
| 210 | // same version of the URI |
| 211 | var newPath, newQuery, newFrag string |
| 212 | |
| 213 | if path != "" { |
| 214 | path = escapePathPlaceholders(path, r, repl) |
| 215 | newPath = repl.ReplaceAll(path, "") |