大猩猩Golang Pathprefix不提供文件

时间:2018-09-05 18:37:34

标签: file http go gorilla fileserver

我在Golang项目目录的根目录files中的文件夹test.jpg中有一个文件。因此,这就是./files/test.jpg,我想为自己的前端服务,而我遇到了困难。

我的golang项目在一个docker文件中,并附加了以下卷。 (基本上,这表示Docker容器中的/go/.../webserver可以在服务器上的./进行读写)

volumes:
  - ./:/go/src/github.com/patientplatypus/webserver/

我使用gorilla/mux进行路由,定义如下:

r := mux.NewRouter()

以下是我尝试获取正确格式的PathPrefix的一些尝试:

r.PathPrefix("/files/").Handler(http.StripPrefix("/files/", 
http.FileServer(http.Dir("/go/src/github.com/patientplatypus/webserver/files/"))))

r.PathPrefix("/files").Handler(http.FileServer(http.Dir("./files/")))

r.PathPrefix("/files/").Handler(http.StripPrefix("/files/",  
http.FileServer(http.Dir("./"))))

r.PathPrefix("/files/").Handler(http.FileServer(
http.Dir("/go/src/github.com/patientplatypus/webserver/")))

我以前已经使用以下命令成功写入服务器:

newPath := filepath.Join("/go/src/github.com/patientplatypus/webserver/files", 
"test.jpg")
newFile, err := os.Create(newPath)

所以我的直觉是,我的第一次尝试应该是正确的尝试,具体说明整个/go/.../files/路径。

无论如何,我的每一次尝试都成功返回200OK到我的前端,并且一个空的响应。数据,如下所示:

Object { data: "", status: 200, statusText: "OK",
headers: {…}, config: {…}, request: XMLHttpRequest }

这是来自使用axios软件包的简单js前端http请求:

        axios({
            method: 'get',
            url: 'http://localhost:8000/files/test.jpg',
        })
        .then(response => {
            //handle success
            console.log("inside return for test.jpg and value 
            of response: ")
            console.log(response);
            console.log("value of response.data: ")
            console.log(response.data)
            this.image = response.data;
        })
        .catch(function (error) {
            //handle error
            console.log(error);
        });

对于为什么会发生这种情况,我唯一的猜测是它看不到文件,因此什么也不返回。

对于这样一个看似微不足道的问题,我正处于猜测和检查阶段,而且我不知道如何进一步调试。如果有人有任何想法,请告诉我。

谢谢!

编辑:

为了清楚起见,这是我的main.go文件的全部内容(仅150行)以及所有路由。有一个中间件可以处理JWT身份验证,但是在这种情况下,它会忽略此路由,并且有一个中间件可以处理CORS。

有问题的行突出显示:https://gist.github.com/patientplatypus/36230e665051465cd51291e17825f1f5#file-main-go-L122

此外,这是我的docker-compose文件,其中显示了卷的大小(请忽略sleep命令来启动postgres-我知道这不是理想的实现)

https://gist.github.com/patientplatypus/2569550f667c0bee51287149d1c49568

应该没有其他必要的信息来调试。

也...有些人希望我证明文件存在于容器中。

patientplatypus:~/Documents/zennify.me:11:49:09$docker exec 
backend_app_1 ls /go/src/github.com/patientplatypus/webserver/files
test.jpg

表明确实如此。

澄清:

我没有正确地使用Axios缓冲阵列并获取图像。这样的工作示例在这里:

        //working example image
        var imageurl = 'https://avatars2.githubusercontent.com/u/5302751?v=3&s=88';
        //my empty server response
        //var imageurl = 'http://localhost:8000/files/test.jpg';
        axios.get(imageurl, {
            responseType: 'arraybuffer'
        })
        .then( response => {
            console.log('value of response: ', response);
            console.log('value of response.data: ', response.data);
            const base64 = btoa(
                new Uint8Array(response.data).reduce(
                    (data, byte) => data + String.fromCharCode(byte),
                    '',
                ),
            );
            console.log('value of base64: ', base64);
            this.image = "data:;base64," + base64 
        });

但是,这并没有改变潜在的问题,即golang不会返回任何数据(response.data为空)。仅供参考,我已经确认axios可以正常工作,并且不能解决问题。

4 个答案:

答案 0 :(得分:1)

您可以从中删除JavaScript客户端,并进行简单的curl请求吗?用简单的文本文件替换图像,以消除任何可能的Content-Type / MIME检测问题。

(略)改编在gorilla/mux文档中发布的示例:https://github.com/gorilla/mux#static-files

代码

func main() {
    var dir string

    flag.StringVar(&dir, "dir", ".", "the directory to serve files from. Defaults to the current dir")
    flag.Parse()
    r := mux.NewRouter()

    r.PathPrefix("/files/").Handler(
        http.StripPrefix("/files/",
            http.FileServer(
                http.Dir(dir),
            ),
        ),
    )

    addr := "127.0.0.1:8000"
    srv := &http.Server{
        Handler:      r,
        Addr:         addr,
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    log.Printf("listening on %s", addr)
    log.Fatal(srv.ListenAndServe())
}

运行服务器

➜  /mnt/c/Users/matt/Dropbox  go run static.go -dir="/home/matt/go/src/github.com/gorilla/mux"
2018/09/05 12:31:28 listening on 127.0.0.1:8000

获取文件

➜  ~  curl -sv localhost:8000/files/mux.go | head
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /files/mux.go HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Content-Length: 17473
< Content-Type: text/plain; charset=utf-8
< Last-Modified: Mon, 03 Sep 2018 14:33:19 GMT
< Date: Wed, 05 Sep 2018 19:34:13 GMT
<
{ [16384 bytes data]
* Connection #0 to host localhost left intact
// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mux

import (
        "errors"
        "fmt"
        "net/http"

请注意,实现此目标的“正确”方法与您的第一个示例相同:

r.PathPrefix("/files/").Handler(http.StripPrefix("/files/", 
http.FileServer(http.Dir("/go/src/github.com/patientplatypus/webserver/files/"))))
  • 从路径中剥离/files/前缀,以便文件服务器不会尝试查找/files/go/src/...
  • 确保/go/src/...是正确的-您提供的是文件系统根目录的绝对路径,而不是主目录的绝对路径(这是您的意图吗?)
  • 如果这是您的意图,请确保运行应用程序的用户可以读取/go/src/...

答案 1 :(得分:0)

我通常只是将文件资产捆绑到我的已编译应用程序中。然后,无论您是在容器中还是本地运行,应用程序都将以相同的方式运行并检索资产。这里是a link的一种方法。我过去曾使用过go-bindata,但似乎不再维护此软件包,但是有很多alternatives available

答案 2 :(得分:0)

因此,这不是一个很好的解决方案,但它可以工作(目前)。我看到了这篇文章:Golang. What to use? http.ServeFile(..) or http.FileServer(..)?,显然您可以使用较低级别的API servefile,而不是使用添加了保护的文件服务器。

这样我就可以使用

r.HandleFunc("/files/{filename}", util.ServeFiles)

func ServeFiles(w http.ResponseWriter, req *http.Request){
    fmt.Println("inside ServeFiles")
    vars := mux.Vars(req)
    fileloc := "/go/src/github.com/patientplatypus/webserver/files"+"/"+vars["filename"]
    http.ServeFile(w, req, fileloc)
}

同样不是一个很好的解决方案,我也不感到兴奋-为了防止1337h4x0rZ,我必须在get request参数中传递一些auth内容。如果有人知道如何启动和运行pathprefix,请告诉我,我可以进行重构。谢谢大家的帮助!

答案 3 :(得分:0)

我和您在同一页面上,完全一样,并且我一直在研究这个东西以使其整日工作。我curl缩着,它还给了我200个0字节的信息,就像您在上面的评论中提到的那样。我在指责码头工人。

终于奏效了,唯一的(...)更改是我删除了http.Dir()

中的斜杠

例如:在您的示例中,请执行以下操作:http.FileServer(http.Dir("/go/src/github.com/patientplatypus/webserver/files")))),请勿添加最后一个斜杠使其成为.../files/

它奏效了。它显示了图片,以及卷曲结果:

HTTP/2 200 
 accept-ranges: bytes
 content-type: image/png
 last-modified: Tue, 15 Oct 2019 22:27:48 GMT
 content-length: 107095