Webdav Server in Go - go

I want to implement a webdav-server with Go and found a new "x" package here:
But I don't know how to use this package to get it done.
Can someone help me with this issue?
I tried this:
func main(){
fs := new(webdav.FileSystem)
ls := new(webdav.LockSystem)
h := new(webdav.Handler)
h.FileSystem = *fs
h.LockSystem = *ls
//then use the Handler.ServeHTTP Method as the http.HandleFunc
http.HandleFunc("/", h.ServeHTTP)
http.ListenAndServe(":5555", nil)
}
If I try to connect to the server, I get an internal server error.
What am I doing wrong?
Thanks for your help.

The x/net/webdav is still in early phase of development. Many critical parts are still being implemented, and it can not be used as such at this moment. Taking a look at the source code over half of the necessary structures and functions are still completely missing.
Unfortunately there are no Go based webdav server implementations at this moment. (In case someone can correct me, please feel free to do so!)

func main(){
fs := new(webdav.FileSystem)
ls := new(webdav.LockSystem)
h := new(webdav.Handler)
h.FileSystem = fs
h.LockSystem = ls
//then use the Handler.ServeHTTP Method as the http.HandleFunc
http.HandleFunc("/", h.ServeHTTP)
http.ListenAndServe(":5555", nil)
}
try to remove the * before "fs" and "ls" because they are already pointers.
NB : if you have to assign pointer use & and not *

Create a webdav server on http://localhost:8080/ which mounts the folder C:\myfiles.
package main
import (
"net/http"
"golang.org/x/net/webdav"
)
func main() {
handler := &webdav.Handler{
FileSystem: webdav.Dir(`C:\myfiles`),
LockSystem: webdav.NewMemLS(),
}
http.ListenAndServe("localhost:8080", handler)
}
Mount to Letter E: in windows:
net use e: http://localhost:8080/
Open mounted drive in explorer
explorer.exe e:

Related

Serve static file from within a group with Gin

I want to server static file by mapping /fs to filesys in the disk. I can server static file like this:
r := gin.New()
r.Use(static.Serve("/fs", static.LocalFile("./filesys", false)))
// followed by other routes definition such as R.GET()
I also want to guard access by using a authentication middleware, without affecting other routes. I imagine it's something I need to do with Gin's group like this:
r := gin.New()
g := r.Group("/fs")
{ // what is the purpose of this parenthesis BTW?
g.Use(authMiddleWare)
g.Use(static.Serve("/fs", static.LocalFile(fileUploadDir, false)))
}
However, I can't get it to work. It is not routed in. If I do additional g.GET afterward, the path came out to be wrong.
How to go about this?
Hi I checked this issue has been open for 3 years on git with no solution for 3 years and the static package seems not being maintained anymore
This is an alternate solution that might help you
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
grp := r.Group("/static")
{
grp.StaticFS("", http.Dir("/your_directory"))
}
r.Run()
}

What is the idiomatic way to read urls with a file scheme as filenames for ReadFile?

Is there an idiomatic way to read a file from the system starting from a (file scheme) url and not a path?
I tried this first:
fileUrlStr := "file:///path/to/file.json"
jsonBuffer, _ := ioutil.ReadFile(fileUrlStr)
This is my current (mostly working version) but I'm concerned there are some gotchas that I'm missing, so I'm hoping there's a more tried and true way to do it:
fileUrlStr := "file:///path/to/file.json"
fileUrl, _ := url.Parse(fileUrlStr)
jsonBuffer, _ := ioutil.ReadFile(fileUrl.Path)
(Bonus if I can support both file:///Users/jdoe/temp.json and file:///c:/WINDOWS/clock.json without having to add code-paths accounting for them)
Using net/url, the solution that you were using, is the correct one.
It's properly deals with hostnames and paths across platforms and also gives you a chance to check the url scheme is the file scheme.
package main
import (
"fmt"
"net/url"
)
func main() {
for _, path := range []string{
"file:///path/to/file.json",
"file:///c:/WINDOWS/clock.json",
"file://localhost/path/to/file.json",
"file://localhost/c:/WINDOWS/clock.avi",
// A case that you probably don't need to handle given the rarity,
// but is a known legacy win32 issue when translating \\remotehost\share\dir\file.txt
"file:////remotehost/share/dir/file.txt",
} {
u, _ := url.ParseRequestURI(path)
fmt.Printf("url:%v\nscheme:%v host:%v Path:%v\n\n", u, u.Scheme, u.Host, u.Path)
}
}

Using the go-fuse package in Golang

Hello I'm about to port my two almost working simple fuse filesystems from bazillion fuse to go-fuse. go-fuse api seems more complex.
The question is:
In NewServer(), which RawFileSystem to use?
How to implement callbacks for read, readdir etc.?
Where to use WaitMount()?
What are DeleteNotify(), EntryNotify()?
ok i found the solutions
1.
make a struct that contains nodefs.Node:
type my_root struct {nodefs.Node}
initialize it
my = &my_root{Node: nodefs.NewDefaultNode()}
make a connection and a raw filesystem
con := nodefs.NewFileSystemConnector(my, nil)
raw := fuse.NewRawFileSystem(con.RawFS())
finally, fire up the fuse fs
server, err := fuse.NewServer(raw, f.dir, optz)
like this:
func (my_root) OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {}
func (my_root) Lookup(out *fuse.Attr, name string, context *fuse.Context) (node *nodefs.Inode, code fuse.Status)
after step 1, like this:
server.WaitMount()
i didn't need this.

Download public file from Google Drive - Golang

I have a zip file stored on Google Drive (it is shared publicly). I want to know how to download it in Golang. This current code just creates a blank file named "file.zip":
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
url := "https://docs.google.com/uc?export=download&id=0B2Q7X-dUtUBebElySVh1ZS1iaTQ"
fileName := "file.zip"
fmt.Println("Downloading file...")
output, err := os.Create(fileName)
defer output.Close()
response, err := http.Get(url)
if err != nil {
fmt.Println("Error while downloading", url, "-", eerrror)
return
}
defer response.Body.Close()
n, err := io.Copy(output, response.Body)
fmt.Println(n, "bytes downloaded")
}
This appears to be a bug, either with Google drive or with golang, I'm not sure which!
The problem is that the first URL you gave redirects to a second URL which looks something like this
https://doc-00-c8-docs.googleusercontent.com/docs/securesc/ha0ro937gcuc7l7deffksulhg5h7mbp1/8i67l6m6cdojptjuh883mu0qqmtptds1/1376330400000/06448503420061938118/*/0B2Q7X-dUtUBebElySVh1ZS1iaTQ?h=16653014193614665626&e=download
Note the * in the URL which is legal according to this stack overflow question. However it does have a special meaning as a delimeter.
Go fetches the URL with the * encoded as %2A like this
https://doc-00-c8-docs.googleusercontent.com/docs/securesc/ha0ro937gcuc7l7deffksulhg5h7mbp1/8i67l6m6cdojptjuh883mu0qqmtptds1/1376330400000/06448503420061938118/%2A/0B2Q7X-dUtUBebElySVh1ZS1iaTQ?h=16653014193614665626&e=download
Which Google replies "403 Forbidden" to.
Google doesn't seem to be resolving the %2A into a *.
According to this article on wikipedia reserved characters (of which * is one) used in a URI scheme: if it is necessary to use that character for some other purpose, then the character must be percent-encoded.
I'm not enough of an expert on this to say who is right, but since Google wrote both parts of the problem it is definitely their fault somewhere!
Here is the program I was using for testing
I found the solution.
Use: https://googledrive.com/host/ID
Instead of: https://docs.google.com/uc?export=download&id=ID
I'm still investigating on why this is happening, in the meanwhile you can use this workaround:
http://play.golang.org/p/SzGBAiZdGJ
CheckRedirect is called when a redirect happens and you can add an Opaque path to avoid having the URL url-encoded.
Francesc

List of currently running process in Go

How can I get the list of currently running processes in Go?
The OS package provides some functions: http://golang.org/pkg/os/
but doesn't give anything to see the list of running processes.
There is no such function in the standard library and most likely never will be.
In most cases, the list of processes isn't required by programs. Go programs usually want to wait for a single or a smaller number of processes, not for all processes. PIDs of processes are usually obtained by other means than searching the list of all processes.
If you are on Linux, the list of processes can be obtained by reading contents of /proc directory. See question Linux API to list running processes?
This library:
github.com/mitchellh/go-ps
worked for me.
import (
ps "github.com/mitchellh/go-ps"
... // other imports here...
)
func whatever(){
processList, err := ps.Processes()
if err != nil {
log.Println("ps.Processes() Failed, are you using windows?")
return
}
// map ages
for x := range processList {
var process ps.Process
process = processList[x]
log.Printf("%d\t%s\n",process.Pid(),process.Executable())
// do os.* stuff on the pid
}
}
I suggest to use for this purpose the following library:
https://github.com/shirou/gopsutil/
Here is an example to get total processes and running ones:
package main
import (
"fmt"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/load"
)
func main() {
infoStat, _ := host.Info()
fmt.Printf("Total processes: %d\n", infoStat.Procs)
miscStat, _ := load.Misc()
fmt.Printf("Running processes: %d\n", miscStat.ProcsRunning)
}
The library allows to get several other data.
Take a look at the documentation for available informations provided according to the target operative system.
If you only need the process information, can just run "ps" command from your go code, then parse the text output.
A complete solution can refer to Exercise 29 in Book "Learning Go" # http://www.miek.nl/files/go/
you can use this library github.com/shirou/gopsutil
package main
import (
"fmt"
"github.com/shirou/gopsutil/v3/process"
)
func main() {
processes, _ := process.Processes()
for _, process := range processes {
name, _ := process.Name()
fmt.Println(name)
}
}
in this library,you can also get process info other
For linux
I found a fairly simple solution to get the list of running processes without using a large library:
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
matches, err := filepath.Glob("/proc/*/exe")
for _, file := range matches {
target, _ := os.Readlink(file)
if len(target) > 0 {
fmt.Printf("%+v\n", target)
}
}
}
It will print the path for each running process. If you need just the process name, then you can get it with filepath.Base(target)
This works by de-referencing the symlink for the /proc/[procID]/exe file, which is a symlink to the executable file. This is much simpler than reading and extracting the process name from the /proc/[procID]/status file (as suggested in other solutions I found).
PS: This might not work on all distribution because it relies on the exe file in the process' folder, which might not present in all flavors of Linux.

Resources