ServeHTTP is the server's implementation of http.Handler.
(w http.ResponseWriter, r *http.Request)
| 117 | |
| 118 | // ServeHTTP is the server's implementation of http.Handler. |
| 119 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 120 | ctx, err := s.ops.NewContext(r) |
| 121 | if err != nil { |
| 122 | http.Error(w, err.Error(), http.StatusInternalServerError) |
| 123 | return |
| 124 | } |
| 125 | |
| 126 | // sumdb handler |
| 127 | if strings.HasPrefix(r.URL.Path, "/sumdb/") { |
| 128 | sumdb.Handler(w, r) |
| 129 | return |
| 130 | } |
| 131 | |
| 132 | i := strings.Index(r.URL.Path, "/@") |
| 133 | if i < 0 { |
| 134 | http.Error(w, "no such path", http.StatusNotFound) |
| 135 | return |
| 136 | } |
| 137 | modPath, err := module.UnescapePath(strings.TrimPrefix(r.URL.Path[:i], "/")) |
| 138 | if err != nil { |
| 139 | http.Error(w, err.Error(), http.StatusNotFound) |
| 140 | return |
| 141 | } |
| 142 | what := r.URL.Path[i+len("/@"):] |
| 143 | const ( |
| 144 | contentTypeJSON = "application/json" |
| 145 | contentTypeText = "text/plain; charset=UTF-8" |
| 146 | contentTypeBinary = "application/octet-stream" |
| 147 | ) |
| 148 | var ctype string |
| 149 | var f File |
| 150 | var openErr error |
| 151 | switch what { |
| 152 | case "latest": |
| 153 | ctype = contentTypeJSON |
| 154 | f, openErr = s.ops.Latest(ctx, modPath) |
| 155 | case "v/list": |
| 156 | ctype = contentTypeText |
| 157 | f, openErr = s.ops.List(ctx, modPath) |
| 158 | default: |
| 159 | what = strings.TrimPrefix(what, "v/") |
| 160 | ext := path.Ext(what) |
| 161 | vers, err := module.UnescapeVersion(strings.TrimSuffix(what, ext)) |
| 162 | if err != nil { |
| 163 | http.Error(w, err.Error(), http.StatusNotFound) |
| 164 | return |
| 165 | } |
| 166 | m := module.Version{Path: modPath, Version: vers} |
| 167 | if vers == "latest" { |
| 168 | // The go command handles "go get m@latest" by fetching /m/@v/latest, not latest.info. |
| 169 | // We should never see requests for "latest.info" and so on, so avoid confusion |
| 170 | // by disallowing it early. |
| 171 | http.Error(w, "version latest is disallowed", http.StatusNotFound) |
| 172 | return |
| 173 | } |
| 174 | // All requests require canonical versions except for info, |
| 175 | // which accepts any revision identifier known to the underlying storage. |
| 176 | if ext != ".info" && vers != module.CanonicalVersion(vers) { |