1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
15 // serveS3 handles r and returns true if r is a request from an S3
16 // client, otherwise it returns false.
17 func (h *handler) serveS3(w http.ResponseWriter, r *http.Request) bool {
19 if auth := r.Header.Get("Authorization"); strings.HasPrefix(auth, "AWS ") {
20 split := strings.SplitN(auth[4:], ":", 2)
22 w.WriteHeader(http.StatusUnauthorized)
26 } else if strings.HasPrefix(auth, "AWS4-HMAC-SHA256 ") {
27 w.WriteHeader(http.StatusBadRequest)
28 fmt.Println(w, "V4 signature is not supported")
34 _, kc, client, release, err := h.getClients(r.Header.Get("X-Request-Id"), token)
36 http.Error(w, "Pool failed: "+h.clientPool.Err().Error(), http.StatusInternalServerError)
41 r.URL.Path = "/by_id" + r.URL.Path
43 fs := client.SiteFileSystem(kc)
44 fs.ForwardSlashNameSubstitution(h.Config.cluster.Collections.ForwardSlashNameSubstitution)
48 fi, err := fs.Stat(r.URL.Path)
49 if os.IsNotExist(err) {
50 http.Error(w, err.Error(), http.StatusNotFound)
52 } else if err != nil {
53 http.Error(w, err.Error(), http.StatusInternalServerError)
55 } else if fi.IsDir() {
56 http.Error(w, "not found", http.StatusNotFound)
58 http.FileServer(fs).ServeHTTP(w, r)
61 f, err := fs.OpenFile(r.URL.Path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
62 if os.IsNotExist(err) {
63 // create missing intermediate directories, then try again
64 for i, c := range r.URL.Path {
65 if i > 0 && c == '/' {
67 err := fs.Mkdir(dir, 0755)
68 if err != nil && err != os.ErrExist {
69 err = fmt.Errorf("mkdir %q failed: %w", dir, err)
70 http.Error(w, err.Error(), http.StatusInternalServerError)
75 f, err = fs.OpenFile(r.URL.Path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
78 err = fmt.Errorf("open %q failed: %w", r.URL.Path, err)
79 http.Error(w, err.Error(), http.StatusBadRequest)
83 _, err = io.Copy(f, r.Body)
85 err = fmt.Errorf("write to %q failed: %w", r.URL.Path, err)
86 http.Error(w, err.Error(), http.StatusBadGateway)
91 err = fmt.Errorf("write to %q failed: %w", r.URL.Path, err)
92 http.Error(w, err.Error(), http.StatusBadGateway)
97 err = fmt.Errorf("sync failed: %w", err)
98 http.Error(w, err.Error(), http.StatusInternalServerError)
101 w.WriteHeader(http.StatusOK)
104 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)