L'éditeur PHP Zimo vous présente une méthode pour vous connecter au code Golang du serveur FTP en utilisant un proxy. Dans certains cas, nous devrons peut-être utiliser un serveur proxy lors de l'accès au serveur FTP afin d'augmenter la sécurité ou de résoudre les restrictions réseau. Golang est un langage de programmation puissant avec des bibliothèques réseau simples et faciles à utiliser, nous pouvons donc facilement implémenter cette fonctionnalité. Ensuite, nous utiliserons un exemple de code simple pour montrer comment utiliser Golang pour se connecter à un serveur FTP via un proxy.
Je dois me connecter au serveur FTP via un proxy et télécharger des fichiers à partir du code Golang. J'ai implémenté un client simple :
<code>package main import ( "bufio" "fmt" "github.com/jlaffaye/ftp" "io" "log" "net" "net/http" "os" "strings" "time" ) var targetAddr = "ftp.dlptest.com" var proxyAddr = "146.19.106.109:3128" var user = "dlpuser" var pass = "rNrKYTX9g7z3RgJRmxWuGHbeu" var path = "/xxx.txt" func connectViaProxy(network, address string) (net.Conn, error) { parts := strings.Split(address, ":") addr := fmt.Sprintf("%s:%s", targetAddr, parts[1]) proxyConn, err := net.Dial(network, proxyAddr) if err != nil { return nil, err } req, err := http.NewRequest(http.MethodConnect, "http://"+addr, nil) if err != nil { proxyConn.Close() return nil, err } req.Header.Set("Accept", "*/*") req.Header.Set("User-Agent", "curl/8.1.2") req.Header.Set("Host", targetAddr+":21") err = req.Write(proxyConn) if err != nil { return nil, err } resp, err := http.ReadResponse(bufio.NewReader(proxyConn), req) if err != nil { proxyConn.Close() return nil, err } if resp.StatusCode != 200 { x, _ := io.ReadAll(resp.Body) fmt.Println(string(x)) proxyConn.Close() return nil, fmt.Errorf("non-200 status code received from proxy: %v", resp.Status) } return proxyConn, nil } func main() { c, err := ftp.Dial(targetAddr+":21", ftp.DialWithTimeout(5*time.Second), ftp.DialWithDebugOutput(os.Stdin), ftp.DialWithDialFunc(connectViaProxy), ) if err != nil { log.Fatal(err) } err = c.Login(user, pass) if err != nil { log.Fatal(err) } if r, err := c.Retr(path); err != nil { fmt.Println(err, ":<") } else { if reader, err := io.ReadAll(r); err != nil { fmt.Println(err, ":(") } else { fmt.Println(string(reader)) } } if err = c.Quit(); err != nil { log.Fatal(err) } } </code>
Malheureusement, je reçois un 403 Forbidden lorsque j'essaie de me connecter. Normalement, je suppose qu'il s'agit d'une limitation du serveur, mais via curl, cela fonctionne parfaitement :
curl -vvv -x 146.19.106.109:3128 -u dlpuser:rNrKYTX9g7z3RgJRmxWuGHbeu ftp://ftp.dlptest.com/xxx.txt
Est-ce que quelqu'un sait pourquoi cela se produit ? Pour autant que je sache, curl utilise également http CONNECT sous le capot, donc je me demande ce qui me manque.
P.S. Ne vous inquiétez pas des informations d'identification dans le code - elles sont exposées pour les tests réseau
FTP sur le proxy HTTP n'est pas effectué via la requête CONNECT. Au lieu de cela, le proxy est invité à obtenir l'URL ftp://...
à l'aide d'une requête GET normale. C’est aussi ce que fait curl. En Go, cela peut être fait comme ceci (gestion des erreurs omise pour plus de simplicité) :
// create the TCP connection to the proxy conn, err := net.Dial("tcp", "146.19.106.109:3128") // create the request with the ftp:// URL req, err := http.NewRequest(http.MethodGet, "ftp://ftp.dlptest.com/xxx.txt", nil) req.SetBasicAuth("dlpuser","rNrKYTX9g7z3RgJRmxWuGHbeu") // don't use req.Write but req.WriteProxy, since the request line must // contain the full URL and not only the path err = req.WriteProxy(conn) // read response resp, err := http.ReadResponse(bufio.NewReader(conn), req) body, _ := io.ReadAll(resp.Body)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!