Обработчик запросов HTTP PUT с помощью go - PullRequest
0 голосов
/ 07 июня 2019

Пожалуйста, рассмотрите этот образец фрагмента кода Go,

package main

import (
        "fmt"
        "log"
        "net/http"
        "time"
)

func main() {
        listen_at := ":3114"
        go http.Handle("/", http.FileServer(http.Dir(".")))
        //go http.Handle("/max", http.FileServer(http.Dir("."))) <-- Fails
        go http.HandleFunc("/ping", ping_handler)
        log.Fatal(http.ListenAndServe(listen_at, nil))

}

func ping_handler(w http.ResponseWriter, r *http.Request) {
        a := time.Now()
        layout := "2006-01-02-03-04-05-000"

        fmt.Println("Got root!")
        fmt.Println("r is", r)
        fmt.Println("RemoteAddr is", r.RemoteAddr)
        send_this := "OK GOT ping! " + a.Format(layout)
        w.Write([]byte(send_this))
}

У меня есть два вопроса:

(1) Как я могу изменить FileServer для обслуживания /max вместо / - мои попытки не увенчались успехом, я получаю 404 за http://localhost:3114/max/ и http://localhost:3114/max.

(2) Я хочу принять PUT запросов к /max - как мне этого добиться?

Пожалуйста, укажите мне правильное направление, спасибо!

Редактировать 1

package main

import (
        "fmt"
        "log"
        "net/http"
)

func main() {
        go http.HandleFunc("/ping", hello)
        log.Fatal(http.ListenAndServe(":3114", nil))
}

func hello(w http.ResponseWriter, r *http.Request) {
        fmt.Println("STarting hello!")

        log.Println("Got connection")
        if r.URL.Path != "/ping" {
                http.Error(w, "404 not found", http.StatusNotFound)
                return
        }
        log.Println("Method:", r.Method)
        switch r.Method {
        case "GET":
                send_this := "OK GOT ping! "
                w.Write([]byte(send_this))
        case "PUT":
                fmt.Println("We got put!")
                err := r.ParseForm()
                checkErr(err)
                fmt.Println("r now", r)
                fmt.Println("r.Form", r.Form)
                fmt.Println("r.PostForm", r.PostForm)
        default:
                send_this := "Please dont!"
                w.Write([]byte(send_this))
                fmt.Fprintf(w, "Unknown request!")
        }

}

func checkErr(err error) {
        if err != nil {
                fmt.Println("Error", err)
        }
}

Я отправляю запрос PUT как curl -k http://localhost:3114/ping -T /tmp/a.go -v, он показывает:

STarting hello!
2019/06/07 15:05:10 Got connection
2019/06/07 15:05:10 Method: PUT
We got put!
r now &{PUT /ping HTTP/1.1 1 1 map[Content-Length:[10115] Expect:[100-continue] User-Agent:[curl/7.47.0] Accept:[*/*]] 0xc4200ec2e0 <nil> 10115 [] false localhost:3114 map[] map[] <nil> map[] 127.0.0.1:64612 /ping <nil> <nil> <nil> 0xc42005e340}
r.Form map[]
r.PostForm map[]

Как мне найтифактические данные, а имя файла, которое пришло из PUT?

1 Ответ

2 голосов
/ 08 июня 2019

С https://golang.org/pkg/net/http/#ServeMux:

Исправлено имя шаблона, корневые пути, такие как "/favicon.ico" или root поддеревья, например "/ images /" (обратите внимание на косую черту) .

Это означает, что /max, который является фиксированным корневым путем , будет соответствовать только /max, а шаблон /max/, который является корневым поддеревом , будет соответствовать /max/, любой другой путь, начинающийся с /max/, и по умолчанию он также будет соответствовать /max.

http.Handle("/max/", http.FileServer(http.Dir(".")))

В зависимости от расположения вашего каталога . может потребоваться использовать https://golang.org/pkg/net/http/#StripPrefix.

Допустим, ваш каталог содержит два файла:

.
├── foo.txt
└── max
    └── bar.txt

Учитывая вышеописанный обработчик, запрос к /max/bar.txt вернет файл bar.txt, но запрос к /max/foo.txt или /foo.txt вернет 404, файла нет.

Таким образом, если вы хотите обслуживать файлы из пути /max/, но в вашем каталоге . нет подкаталога max, вы можете использовать StripPrefix для удаления префикса /max из путь URL запроса до его передачи на FileServer.

http.Handle("/max/", http.StripPrefix("/max/", http.FileServer(http.Dir("."))))

Для обработки PUT запросов по одному и тому же маршруту вам нужен пользовательский обработчик.

type myhandler struct {
    fs http.Handler
}

func (h myhandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if r.Method != "PUT" {
        // business as usual
        h.fs.ServeHTTP(w, r)
        return
    }

    // handle PUT
    // ...
}

А затем, чтобы зарегистрировать его, выполните:

fs := http.StripPrefix("/max/", http.FileServer(http.Dir(".")))
http.Handle("/max/", myhandler{fs: fs})
...