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
Tutorials
+13.8k Golang : How to convert a number to words
+6.4k Golang : Muxing with Martini example
+13.6k Golang : Google Drive API upload and rename example
+13.7k Golang : Chunk split or divide a string into smaller chunk example
+6.2k Golang : Embedded or data bundling example
+12.8k Android Studio : Password input and reveal password example
+5.2k Unix/Linux/MacOSx : Get local IP address
+8k Golang : How to check variable or object type during runtime?
+24.4k Golang : Daemonizing a simple web server process example
+14.1k Golang : Overwrite previous output with count down timer
+51.4k Golang : How to get time in milliseconds?