Sometimes you have a really old application which uses an old version of jRuby and can no longer talk to rubygems.org over HTTPS. In ~Dec 2020, Rubygems or Fastly removed TLSv1.1 support. I don’t blame them but it caused a couple issues installing gems on old software.
You might see one of these sorts of errors:
Error fetching https://rubygems.org/:
Received fatal alert: handshake_failure (https://api.rubygems.org/specs.4.8.gz)
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
Received fatal alert: handshake_failure (https://api.rubygems.org/api/v1/dependencies)
Below is Go program that is a proxy server which upgrades http://
requests to https://
. Simples right?
By default if you change the gem sources to http://rubygems.org
, you might get the second error as they 301 redirect you to the secure version.
This is where this proxy comes in.
How to use
- Remove the https version of rubygems from sources:
gem sources --remove https://rubygems.org/
- Add the http version of rubygems:
gem sources --add http://rubygems.org/
- Build proxy server:
go build -o rubygems-proxy
- Run the proxy server:
./rubygems-proxy
. If you’re lazy, you can build/run at the same time:go run proxy.go
- Install your gems:
gem install --http-proxy http://localhost:8989 vault
- All should work, fingers crossed. There’s some logging in the proxy to see the requests going by.
Notes
- I’m very new to Go, this was made using StackOverflow Driven Development
- It’s a workaround, this proxy shouldn’t be used for anything more than getting out of a pinch
- Keep your software updated and you should’t have to figure out these workarounds
The source
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
)
func main() {
proxy := NewHTTPSUpgradeReverseProxy()
fmt.Println("Awake and listening on :8989")
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
log.Printf("%#v", req.URL)
proxy.ServeHTTP(w, req)
})
err := http.ListenAndServe(":8989", nil)
if err != nil {
panic(err)
}
}
// NewHTTPSUpgradeReverseProxy upgrades http requests to https
func NewHTTPSUpgradeReverseProxy() *httputil.ReverseProxy {
director := func(req *http.Request) {
req.URL.Scheme = "https" // Where the magic happens
}
return &httputil.ReverseProxy{Director: director}
}