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
GET /in the error error thatcurlis not requesting/hellobecause the url is incorrect. You are also trying to write the response header a second time, which does nothing because you cannot change the response after it has already been sent.