HTTP/2 es una versión más moderna y eficiente de HTTP que tiene algunas diferencias importantes con respecto a HTTP/1. En HTTP/2, todos los headers son transmitidos en formato binario y se espera que sean en minúscula. Esto significa que si envía un encabezado con mayúsculas, es posible que no sean reconocidos por el servidor y, por lo tanto, no se procesen correctamente.

Por ejemplo, si mandamos un header como POWERED_BY sin avisar y sin mostrar ningun tipo de log o warning el cliente de HTTP/2 va a modificar y enviar el header como powered_by Causando que el servicio que esta esperando el header todo en mayusculas, lo reciba todo en minusculas, eso haria que no encuentre el header y por lo tanto entienda que el header no fue enviado, ejecundo un flujo totalmente distinto.

En algunos casos, no tenemos acceso al API en cuestion para modificar el header esperado, por lo que la solución es usar HTTP/1 en lugar de HTTP/2. HTTP/1 no tiene restricciones en cuanto a la forma en que los headers deben ser transmitidos, por lo que podemos enviar headers con mayúsculas, camelCase, etc sin problemas.

Si estás desarrollando en Go y queres forzar al cliente a hacer un request con HTTP/1, podes hacerlo usando la lib estándar “net/http”. Para eso, tenes que crear un cliente HTTP con la opción “Transport” especificando la versión HTTP que deseas usar. Ejemplo en código:

package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	// Creamos un cliente HTTP con la opción "Transport" especificando que se desea usar HTTP/1
	client := &http.Client{
		Transport: &http.Transport{
			// Deshabilitamos el protocolo TLSNextProto
			TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
		},
	}

	// Realizamos la solicitud usando el cliente HTTP creado
	req, err := http.NewRequest("GET", "https://example.com/", nil)

	// Es importante que los headers los setiemos de esta manera ya que si usamos Add() o Set()
	// Pasa por un proceso de canonicalizado que termina modificando el header tambien por mas que
	// Usemos HTTP/1
	req.Header = map[string][]string{
		"POWERED_BY": {"GO"},
	}
	if err != nil {
		fmt.Println(err)
	}

	resp, err := client.Do(req)

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

	defer resp.Body.Close()

	// Leemos el contenido de la respuesta
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}

	// Imprimimos el contenido de la respuesta
	fmt.Println(string(body))
}

Ejemplo de request recibida por HTTP/2 alt

Ejemplo de request recibida por HTTP/1 alt

En resumen, si estás teniendo problemas con los headers en HTTP/2, podes solucionarlo usando HTTP/1 y forzando a tu cliente de Go a hacer la solicitud con esta versión de HTTP. Para eso, tenes que crear un cliente HTTP con la opción “Transport” deshabilitada