Reputation: 567
I am trying to write a simple Unix domain socket based http server in golang. Here is the code:
package main
import (
"fmt"
"log"
"net/http"
"net"
"os"
"encoding/json"
"os/signal"
"syscall"
)
type UnixListener struct {
ServerMux *http.ServeMux
SocketPath string
UID int
GID int
SocketFileMode os.FileMode
}
//////////////////////////////////////////////////////////////////////
// Start the HTTP server with UNIX socket.
//////////////////////////////////////////////////////////////////////
func (l *UnixListener) Start() error {
listener, err := net.Listen("unix", l.SocketPath)
if err != nil {
return err
}
if err := os.Chown(l.SocketPath, l.UID, l.GID); err != nil {
return err
}
if err := os.Chmod(l.SocketPath, l.SocketFileMode); err != nil {
return err
}
go func(){
shutdown(listener)
}()
svr := http.Server{
Handler: l.ServerMux,
}
if err := svr.Serve(listener); err != nil {
return err
} else {
return nil
}
}
//////////////////////////////////////////////////////////////////////
// Shutdown the HTTP server.
//////////////////////////////////////////////////////////////////////
func shutdown(listener net.Listener) {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
s := <-c
listener.Close()
log.Fatalf("[FATAL] Caught a signal. sinal=%s", s)
}
func hello(w http.ResponseWriter, r *http.Request) {
log.Println("Received request %s", r.RequestURI)
fmt.Fprintf(w, "Hello World!\n")
w.Header().Set("ContentType", "application/json")
w.WriteHeader(http.StatusOK)
data := map[string]string { "name" : "satish"}
resp, _ := json.Marshal(data)
if _, err := w.Write(resp); err != nil {
fmt.Printf("Error writing response")
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/hello", hello)
unixListener := UnixListener{
ServerMux: mux,
SocketPath: "/temp/test.sock",
UID: 501,
GID: 20,
SocketFileMode: 0644,
}
if err := unixListener.Start(); err != nil {
log.Fatalf("[FATAL] HTTP server error: %s", err)
}
}
But when I send the request to this UDS based server like below, the handler does not seem to be invoked, giving 404 not found error. What is the right way to implement UDS based http server and how to send the http request to it?
curl -vvv --unix-socket /temp/test.sock http:/hello
* Trying /Users/sburnwal/Projects/ACI/temp/test.sock:0...
* Connected to hello (/temp/test.sock) port 80 (#0)
> GET / HTTP/1.1
> Host: hello
> User-Agent: curl/7.84.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Mon, 14 Nov 2022 02:38:11 GMT
< Content-Length: 19
<
404 page not found
* Connection #0 to host hello left intact
Upvotes: 1
Views: 743
Reputation: 104589
It appears it's interpreting http:/hello
in your command line as the host name and using that for the header. And then requesting /
as the path
Try replacing http:/hello
in your command line with http://hello/hello
. I'm not sure if the single slash vs double-slash is significant. It just looks suspicious.
curl -vvv --unix-socket /temp/test.sock http://hello/hello
Or change your Go code to have a response handler for "/"
instead of just for "/hello"
mux.HandleFunc("/hello", hello)
mux.HandleFunc("/", hello)
Upvotes: 2