Home > Mobile >  Make HTTP Request with an absolute URL in the Request URL
Make HTTP Request with an absolute URL in the Request URL

Time:02-25

I was wondering if it's possible to make a request as follows using Go's net/http library:

GET http://test2.com/thisisatest HTTP/1.1
Host: test1.com

To clarify, if I'm sending a request to localhost I don't want to change the host header as in:

nc -lnvp 8001
listening on [any] 8001 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 55122
GET /headers HTTP/1.1
Host: not-localhost
User-Agent: Go-http-client/1.1
Content-Type: application/json
Accept-Encoding: gzip

But what I intend is to have the full URL in the request line:

nc -lnvp 8001
listening on [any] 8001 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 55122
GET http://localhost/headers HTTP/1.1
Host: localhost
User-Agent: Go-http-client/1.1
Content-Type: application/json
Accept-Encoding: gzip

I can't seem to find any information about it. If it's not possible using net/http is there any other way that this would be doable?

Thank you!

Diego

CodePudding user response:

From https://pkg.go.dev/net/http#Request.Host,

// For client requests, Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host. Host may contain an international
// domain name.

So you should be able to craft your request, set it's Host field to whatever you desire, and then make the request.

Consider the following code. It doesn't work on the Playground (which won't allow external connections) but should work on your workstation.

package main

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

func main() {
    client := &http.Client{}
    req, err := http.NewRequest("GET", "https://httpbin.org/headers", nil)
    if err != nil {
        panic(err)
    }
    req.Host = "myserver.com"
    req.Header.Add("Content-Type", `application/json`)
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    } else if _, err := io.Copy(os.Stdout, resp.Body); err != nil {
        panic(err)
    }
}

https://httpbin.org/headers returns the headers sent with a request, so it is a useful way to verify this works. My results:

{
  "headers": {
    "Accept-Encoding": "gzip",
    "Content-Type": "application/json",
    "Host": "myserver.com",
    "User-Agent": "Go-http-client/2.0",
    "X-Amzn-Trace-Id": "Root=1-6217a78b-27317e7e06a097cb293b5db1"
  }
}

As you can see, since I set the request Host, the http library didn't set it from the URL.

In this case, httpbin request handler doesn't mind that the request header doesn't match the url. Other sites might return a 400 Bad Request if the host header does not match.

Note that you cannot achieve the same by maniuplating a Host header directly. You must use Request.Host.

CodePudding user response:

No, this us undoable with net/http because net/http implements HTTP and what you want to do simply isn't HTTP.

If it's not possible using net/http is there any other way that this would be doable?

Do raw networking, i.e. use package net.

This is wrong. Sorry.

  • Related