Golang : Get HTTP protocol version example




Upgraded socketloop.com's NGINX web server to serve via HTTP/2 and wanted to find out if Golang can detect the HTTP/2 protocol version. However, at this moment (Go 1.5), Golang's client will always return protocol version HTTP/1.1

From https://golang.org/pkg/net/http/#Request :

 // The protocol version for incoming requests.
 // Client requests always use HTTP/1.1.

Pretty sure HTTP/2 detection is available at https://godoc.org/golang.org/x/net/http2#ClientConn, but better to wait till it is incorporated into Go 1.6.

Here is a simple example on how to find out the protocol version use by the client in making request to server.

 package main

 import (
 "fmt"
 "net/http"
 "os"
 )

 func main() {

 client := &http.Client{}

 url := "https://www.google.com"

 resp, err := client.Get(url) // can use http directly instead of client

 if err != nil {
 fmt.Println(err)
 os.Exit(1)
 }

 // get protocol version
 protocol := resp.Request.Proto

 fmt.Println("URL is : ", url)
 fmt.Println("Protocol is : ", protocol)

 }

Sample outputs :

URL is : //www.socketloop.com

Protocol is : <----- missing protocol!

URL is : https://www.socketloop.com

Protocol is : HTTP/1.1

URL is : http://www.google.com

Protocol is : HTTP/1.1

URL is : https://www.google.com

Protocol is : HTTP/1.1

Apparently, attempt to get protocol version from NON-HTTPS (//www.socketloop.com) version of socketloop.com will return empty string. Upon further investigation with curl -I command, Golang's net/http.Request.Proto will only returns value if the HTTP status code is 200 - OK.

>curl -I //www.socketloop.com

HTTP/1.1 301 Moved Permanently

>curl -I https://www.socketloop.com

HTTP/1.1 200 OK

Tried to improve the protocol detection by getting Request header information from the final/effective URL, but it seems that after resolving to the final/effective URL, the protocol variable will still be returned as empty string. (See how to get the HTTP status code https://www.socketloop.com/tutorials/golang-intercept-and-compare-http-response-code-example)

Hence, it is best to check for the protocol string length first before displaying the version.

 package main

 import (
 "fmt"
 "net/http"
 "os"
 )

 func main() {

 client := &http.Client{}

 url := "//www.socketloop.com" // has 301 redirect

 resp, err := client.Get(url)

 if err != nil {
 fmt.Println(err)
 os.Exit(1)
 }

 // get protocol version
 protocol := resp.Request.Proto

 if len(protocol) > 0 {
 fmt.Println("URL is : ", url)
 fmt.Println("Protocol is : ", protocol)
 } else {
 fmt.Println("URL is : ", url)
 fmt.Println("Unable to determine protocol version. Check URL with curl -I to see if HTTP status code is 301")
 fmt.Println("Golang will resolve to the final/effective URL and will not return HTTP status 301, but 200. However, it will still return empty string for Proto ")
 }

 }

Output :

With 301 redirect :

URL is : //www.socketloop.com

Unable to determine protocol version. Check URL with curl -I to see if HTTP status code is 301

Golang will resolve to the final/effective URL and will not return HTTP status 301, but 200. However, it will still return empty string for Proto

and with 200 - OK :

URL is : https://www.socketloop.com

Protocol is : HTTP/1.1

References :

https://godoc.org/golang.org/x/net/http2

https://golang.org/pkg/net/http/#Request

https://www.socketloop.com/tutorials/golang-intercept-and-compare-http-response-code-example

https://www.socketloop.com/tutorials/golang-get-final-or-effective-url-with-request-url-example

  See also : Golang : Get final or effective URL with Request.URL example





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement