How to test http.Redirect target URL in golang - go

I have set up a http redirect in the go handler, and I'm trying to verify if the target URL is composed as expected.
I'm currently using httptest for relevant unit test.
In the handler:
url := fmt.Sprintf("%s%s?token=%s", domain, someURL, token)
http.Redirect(w, r, url, 302)
The current unit test can only verify the respond code but not the target URL:
resp := httptest.NewRecorder()
router.ServeHTTP(resp, req)
assert.Equal(t, 302, resp.Code)
I'm expecting something like
assert.Equal(t, expectedURL, resp.redirectURL)

Assert that the Location header is as expected:
assert.Equal(t, expectedURL, resp.HeaderMap.Get("Location"))

Related

Golang net/http/httptest error crypto/x509.unknownauthorityerror

I am trying to mock out a response from a HTTPS web service responding to my Golang package.
In my unit test I am using net/http/httptest.
My function is
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello")
}))
defer ts.Close()
tr := &http.Transport{TLSClientConfig: &TLS.Config{InsecureSkipVerify: true}}
client := ts.Client()
client= &http.Client{Transport:tr}
res, err := client.Get(ts.URL)
When I step through the code and my package makes the call to the mock service, it errors with error (crypto/x509.UnknownAuthorityError)
I thought the skip verify is meant ignore verifying any certificates? Yes, I am mocking out certificates when my package is instantiated, but for the purpose of the test, I am not interested in the certificates all I want to do is verify the response coming back and the code after.
What am I doing wrong with mocking a HTTPS request response?

GRPC over HTTPS proper client initialization in Go

I'm interfacing from my code certain 3rd party software (particularly chirpstack v4) which provides API via GPRC. When deployed locally, it answers via HTTP and I get the response all right.
However in cluster we have the same server deployed with HTTPS (with letsencrypt certificate, not something private) so I'm trying to add corresponding transport layer security settings, but to my surprise I got then
rpc error: code = Internal desc = unexpected HTTP status code received from server: 400 (Bad Request); malformed header: missing HTTP content-type
I tried adding SetHeader to context with content-type: application/grpc but this won't change anything so I'm not sure it is really about header (moreover that it works with plain HTTP). So I wonder, perhaps anyone can point me some mistake in initialization of transport layer security?
// this is used with plain HTTP
//opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
// this for case of working via HTTPS
opts := []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))}
// also tried NewClientTLSFromCert(x509.SystemCertPool()) - the same
serverAddr := "our-public-address:443"
ctx := context.Background()
conn, err := grpc.Dial(serverAddr, opts...)
if err != nil {
println("Dial error:", err.Error())
return
}
cli := api.NewInternalServiceClient(conn)
req := &api.LoginRequest{Email: "admin", Password: "admin"}
resp, err := cli.Login(ctx, req) // error arises here
if err != nil {
println("login failed", err.Error())
}
Thanks in advance for hints and suggestions!

Golang: Getting the response-redirect URL from an HTTP response

I'm trying to make a HTTP request using http.Get(url) in Go and I want to open the response in a browser. I'm using browser.OpenURL() to launch the system browser, but I cannot figure out how to obtain the response url.
In Python, using the requests library, it is an attribute of the response object.
I can obtain and open it in a browser (using the browser library) like so:
response = requests.get(endpoint)
browser.open(response.url)
How can I accomplish this using http/net library in Go? The response object is a struct that doesn't contain that attribute.
I am trying to call the Spotify API to authenticate an app, and this requires opening a browser window for user input. So far I've got this:
func getAuth(endpoint *url.Url) {
request, _ := http.NewRequest("GET", endpoint.string(), nil)
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
panic(err)
}
headers := resp.Header
page, _ := ioutil.ReadAll(resp.Body)
Where can I obtain the response URL or how can I handle the response so that it opens it in a browser?
Go will update the Request struct on the response if there is a redirect.
resp.Request.URL is what you are looking for.
// Request is the request that was sent to obtain this Response.
// Request's Body is nil (having already been consumed).
// This is only populated for Client requests.
Request *Request
Just get the redirect URL from response header.
redirectURL := resp.Header.Get("Location")

Not able to pass Bearer token in headers of a GET request in Golang

I am using oauth2 to access a third party API. I can get the access token alright, but when I try to call the API by passing the bearer token in the request headers it gives me 401 (Unauthorized) error. Although it works well when I try to do it via POSTMAN by passing headers as (Authorization: Bearer ). But it does not work using go.
Here is the code sample.
url := "http://api.kounta.com/v1/companies/me.json"
var bearer = "Bearer " + <ACCESS TOKEN HERE>
req, err := http.NewRequest("GET", url, nil)
req.Header.Add("authorization", bearer)
client := urlfetch.Client(context)
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
writer.Write([]byte(body)) // Gives 401 Unauthorized error, though same works using POSTMAN
I was able to solve the problem. Actually the problem was two way.
1) The API end point was doing a redirect (302), which was causing a 302 response and then the other API was being called.
2) GO by default does not forward the headers, thus my bearer token was being lost in the middle.
FIX:
I had to override the client's CheckRedirect function and manually pass the headers to the new request.
client.CheckRedirect = checkRedirectFunc
Here is how I forwarded the headers manually.
func checkRedirectFunc(req *http.Request, via []*http.Request) error {
req.Header.Add("Authorization", via[0].Header.Get("Authorization"))
return nil
}

Golang wrong http resquest header

I'm building 2 apis. One make request to another.
To call the api that receives requests, we need to pass a X-Token Header. I'm doing this with Golang
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
req, err := http.NewRequest("GET", "https://localhost:8086/v2/example", nil)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"Error": err.Error()})
}
req.Header.Add("accept", "application/json")
req.Header.Add("content-type", "application/json")
req.Header.Add("x-token", "a2e63ee01401aaeca78be023dfbb8c59")
resp, err := client.Do(req)
In the other API, i get the http header with gin like this:
token := c.Request.Header.Get("x-token")
I dont know why my header arrives with another value and no X-Token. Thanks!
Result of fmt.Printf("%+v", c.Request.Header):
map[User-Agent:[Go-http-client/1.1] Referer:[https://localhost:8086/v2/example] Accept-Encoding:[gzip]]
I don't know where is my x-token, accept and content-type headers....
IMPORTANT
If i make a request with x-token header on Postman to the requested API i get the right header.
If i change the request address on the API that makes requests, e.g httpbin, i get the right header too....
Helo, guys! i found the solution....
I don't know why yet... but i think golang don't handle no trailing slash url's....
https://localhost:8086/v2/example
is different of
https://localhost:8086/v2/example/
That was my problem....
I just copy and past the golang generated code of postman... and that was the "biggest" difference....
Thanks mr. Postman...

Resources