-
Star
(155)
You must be signed in to star a gist -
Fork
(32)
You must be signed in to fork a gist
-
-
Save teknoraver/5ffacb8757330715bcbcc90e6d46ac74 to your computer and use it in GitHub Desktop.
package main | |
import ( | |
"context" | |
"flag" | |
"fmt" | |
"io" | |
"net" | |
"net/http" | |
"os" | |
"strings" | |
) | |
func main() { | |
post := flag.String("d", "", "data to POST") | |
help := flag.Bool("h", false, "usage help") | |
flag.Parse() | |
if *help || len(flag.Args()) != 2 { | |
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "[-d data] /path.socket /uri") | |
flag.PrintDefaults() | |
os.Exit(0) | |
} | |
fmt.Println("Unix HTTP client") | |
httpc := http.Client{ | |
Transport: &http.Transport{ | |
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { | |
return net.Dial("unix", flag.Args()[0]) | |
}, | |
}, | |
} | |
var response *http.Response | |
var err error | |
if len(*post) == 0 { | |
response, err = httpc.Get("http://unix" + flag.Args()[1]) | |
} else { | |
response, err = httpc.Post("http://unix"+flag.Args()[1], "application/octet-stream", strings.NewReader(*post)) | |
} | |
if err != nil { | |
panic(err) | |
} | |
io.Copy(os.Stdout, response.Body) | |
} |
package main | |
import ( | |
"fmt" | |
"net" | |
"net/http" | |
"os" | |
) | |
func main() { | |
if len(os.Args) < 2 { | |
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "/path.sock [wwwroot]") | |
return | |
} | |
fmt.Println("Unix HTTP server") | |
root := "." | |
if len(os.Args) > 2 { | |
root = os.Args[2] | |
} | |
os.Remove(os.Args[1]) | |
server := http.Server{ | |
Handler: http.FileServer(http.Dir(root)), | |
} | |
unixListener, err := net.Listen("unix", os.Args[1]) | |
if err != nil { | |
panic(err) | |
} | |
server.Serve(unixListener) | |
} |
Very nice example!
Cool, Thanks
Good!
Works without any issues, thanks!
Thanks!
To preserve the context, I would recommend:
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) {
dialer := net.Dialer{} // don't know why we need a struct to use DialContext()
return dialer.DialContext(ctx, "unix", flag.Args()[0])
},
I am not sure I understand the purpose of the os.Remove(os.Args[1])
. It seems that it should delete the socket passed as an argument. However, it doesn't. Also if I remove it, I get a bind: address already in use exception
.
It seems that it should delete the socket passed as an argument. However, it doesn't.
Or maybe it does, and then re-creates a new one? I see that after running this code, the permissions on the socket file changed.
Or maybe it does, and then re-creates a new one?
Yes I see that's what's happening.
Or maybe it does, and then re-creates a new one?
Yes I see that's what's happening.
This is because a socket can only be bound once, by recreating a new one, you just make sure that it is a brand new one that will not throw a address already in use exception. Note that if you already have a connection to a previously created socket, this connection will still access the previously created socket. (here with http it is unlikely as connections are short lived, however with classic stream connections this could happen that you have a client that access a socket that is not available anymore to the file system and does not throw an error)
This http.Client
transport override is very helpful, thanks for posting! The golang standard library should incorporate a more straightforward way of handling HTTP traffic over unix domain sockets.
Nice work!
Thanks!
To preserve the context, I would recommend:
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) { dialer := net.Dialer{} // don't know why we need a struct to use DialContext() return dialer.DialContext(ctx, "unix", flag.Args()[0]) },
Hi,
I didn't do this because it wasn't backward compatible with old Go versions
I see!
Thanks!
Thanks!
To preserve the context, I would recommend:
DialContext: func(ctx context.Context, _, addr string) (net.Conn, error) { dialer := net.Dialer{} // don't know why we need a struct to use DialContext() return dialer.DialContext(ctx, "unix", flag.Args()[0]) },
I know this is like, 3 years late, but you need to store it as a variable because DialContext
belongs to (*Dialer)
not (Dialer)
. When you assign it a local value, it can be referenced as *Dialer
. A way around this, is to do this:
return (&net.Dialer{}).DialContext(ctx, "unix", flags.Args()[0])
I like this. Might be worthwhile mentioning the benefits.
Thanks a lot!
Are you sure you can handle the response? response.Body is always empty in my code but I can detect errors or responses at my socket application.
Thank you!
Helped a lot here!
Thank you