Home > Net >  Http Over TLS Golang Not Receiving Headers
Http Over TLS Golang Not Receiving Headers

Time:06-14

I am sending 'User-Agent Header' from my client but not receiving on server-side but when i use browser it works.

server code :

package main

import (
  "crypto/tls"
  "fmt"
  "log"
  "net/http"
  "time"
)

const (
  defaultServerDomain = "localhost:443"
  certPemPath = "./selfsigned.crt"
  privKeyPath = "./selfsigned.key"
)

func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/demo/echo", func(w http.ResponseWriter, req *http.Request) {
    w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
    w.Write([]byte("This is an example server.\n"))
    fmt.Printf("\n\nUserAgent : %s", req.UserAgent())

  })
  cfg := &tls.Config{
    MinVersion:               tls.VersionTLS12,
    CurvePreferences:         []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
    PreferServerCipherSuites: true,
    CipherSuites: []uint16{
      tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
      tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
      tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
      tls.TLS_RSA_WITH_AES_256_CBC_SHA,
    },
  }
  srv := &http.Server{
    ReadHeaderTimeout: 2 * time.Second,
    Addr:              defaultServerDomain,
    Handler:           mux,
    TLSConfig:         cfg,
    TLSNextProto:      make(map[string]func(*http.Server, *tls.Conn, http.Handler), 0),
  }
  log.Fatal(srv.ListenAndServeTLS(certPemPath, privKeyPath))
}

client code :

package main

import (
  "crypto/tls"
  "crypto/x509"
  "fmt"
  "io"
  "log"
  "net/http"
  "os"
  "time"
)

const (
  serverDomain = "https://localhost:443/demo/echo"
  certPemPath  = "./selfsigned.crt"
)

func main() {

  cert, err := os.ReadFile(certPemPath)
  if err != nil {
    log.Fatal(err)
  }
  certPool := x509.NewCertPool()
  if ok := certPool.AppendCertsFromPEM(cert); !ok {
    log.Fatalf("unable to parse cert from %s", certPemPath)
  }

  client := &http.Client{
    Timeout: 2 * time.Second,
    Transport: &http.Transport{
      DisableKeepAlives:  false,
      TLSClientConfig: &tls.Config{
        RootCAs: certPool,
      },
    },
  }

  r, err := http.NewRequest("GET", serverDomain, nil)
  req, err := client.Do(r)
  if err != nil {
    log.Fatal(err)
  }
  req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.7113.93 Safari/537.36")
  defer req.Body.Close()

  html, err := io.ReadAll(req.Body)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("%v\n", req.Status)
  fmt.Printf(string(html))
}

Suppose to get server-side :

UserAgent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0 Waterfox/91.4.2

Instead i get this :

UserAgent : Go-http-client/1.1

But when i use browser in my case waterfox then it works i get

UserAgent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0 Waterfox/91.4.2

Is it something to do with code or certificate i am using selfsinged certificate

CodePudding user response:

I believe that the issue is most likely here:

r, err := http.NewRequest("GET", serverDomain, nil)
req, err := client.Do(r)

The definition for NewRequest is func NewRequest(method, url string, body io.Reader) (*Request, error) and Client.Do func (c *Client) Do(req *Request) (*Response, error). So the code above is probably easier understood as:

req, err := http.NewRequest("GET", serverDomain, nil)
resp, err := client.Do(req) // This returns a response; not  the request

When you call Do the request is made (so the headers must be set before that point). Taking the above rephrasing of your code when you set the headers you would be calling resp.Header.Set... (i.e. you are changing the headers returned by the request; not the request headers).

Change your code to set the headers before calling Do i.e.

req, err := http.NewRequest("GET", serverDomain, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.7113.93 Safari/537.36")
resp, err := client.Do(req)

Note: I have not tested your code in full so there may be other issues

  • Related