duannaoben8011 2018-09-05 18:37 采纳率: 0%
浏览 163

Gorilla Golang Pathprefix不提供文件

I have a file in the folder files located in the root of my Golang project directory called test.jpg. So that would be ./files/test.jpg that I want to serve to my front end and I am having difficulties.

My golang project is in a docker file with the following volume attached. (Basically this says that /go/.../webserver in the docker container can read and write out of ./ on the server)

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

I am using gorilla/mux for routing as defined by:

r := mux.NewRouter()

Here are some of my attempts at trying to get the PathPrefix to be properly formatted:

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

or

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

or

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

or

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

I had previously successfully written to the server with the following command:

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

So my intuition is that the first of my attempts should be the correct one, specfying the entirety of the /go/.../files/ path.

In any case, each of my attempts successfully returns a 200OK to my front end with an empty response.data as shown here:

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

which is coming from a simple js frontside http request using the axios package:

        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);
        });

My only guess as to why this is happening is that it doesn't see the file and so returns nothing.

For such a seemingly trivial problem, I am in the guess and check stage and I don't know how to debug further. If anyone has any ideas please let me know.

Thanks!

EDIT:

In order to be completely clear, here is the entirety of my main.go file (only 150 lines) with all the routing. There is a piece of middleware that handles JWT auth, but in this case it ignores this route, and there is middleware to handle CORS.

Line in question is highlighted: https://gist.github.com/patientplatypus/36230e665051465cd51291e17825f1f5#file-main-go-L122.

Also, here is my docker-compose file that shows what the volumes are (please ignore the sleep command to boot postgres - I understand it's not the ideal implementation)

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

There should be no other information necessary to debug.

Also...some people have wanted me to show that the file exists in the container.

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

Shows that it does.

CLARIFICATION:

I was not properly using Axios to buffer the array, and get an image. An example of that working is here:

        //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 
        });

However, this does not change the underlying problem that it appears that golang is not returning any data (response.data is empty). Just FYI that I have confirmed a working axios and that doesn't fix the issue.

  • 写回答

3条回答 默认 最新

  • douzhang1115 2018-09-05 19:38
    关注

    Can you eliminate the JavaScript client from this, and make a simple curl request? Replace the image with a simple text file to remove any possible Content-Type / MIME detection issues.

    (Slightly) adapting the example posted in the gorilla/mux docs: https://github.com/gorilla/mux#static-files

    Code

    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())
    }
    

    Running the Server

    ➜  /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
    

    Getting a file

    ➜  ~  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"
    

    Note that the "correct" way to achieve this is as per your first example:

    r.PathPrefix("/files/").Handler(http.StripPrefix("/files/", 
    http.FileServer(http.Dir("/go/src/github.com/patientplatypus/webserver/files/"))))
    
    • Strip the /files/ prefix from the path, so that the file-server doesn't attempt to find /files/go/src/... instead.
    • Ensure that /go/src/... is correct - you are providing an absolute path from the root of your filesystem, NOT from your home directory (is this your intent?)
    • If that is your intent, make sure that /go/src/... is readable by the user your application is running as.
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料