英文:
Make HTTP Request with an absolute URL in the Request URL
问题
我想知道是否可以使用Go的net/http
库来发送以下请求:
GET http://test2.com/thisisatest HTTP/1.1
Host: test1.com
为了澄清,如果我发送请求到本地主机,我不想改变主机头,就像这样:
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
但是我想要在请求行中包含完整的URL:
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
我似乎找不到任何相关信息。如果使用net/http
不可能实现,是否有其他方法可以实现这个目标?
谢谢!
Diego
英文:
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
答案1
得分: 2
从https://pkg.go.dev/net/http#Request.Host,
对于客户端请求,Host可选地覆盖要发送的Host标头。如果为空,Request.Write方法将使用URL.Host的值。Host可能包含国际域名。
因此,您应该能够构建您的请求,将其Host
字段设置为您想要的任何内容,然后进行请求。
考虑以下代码。在Playground上无法运行(不允许外部连接),但应该在您的工作站上运行。
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返回与请求一起发送的标头,因此这是一种验证此方法是否有效的有用方式。我的结果:
{
"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"
}
}
如您所见,由于我设置了请求的Host,http库没有从URL中设置它。
在这种情况下,httpbin请求处理程序不介意请求标头与URL不匹配。其他网站可能会在主机标头不匹配时返回400 Bad Request。
请注意,您不能通过直接操作Host
标头来实现相同的效果。您必须使用Request.Host
。
英文:
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
.
答案2
得分: 1
不,使用net/http是无法实现的,因为net/http实现的是HTTP协议,而你想要做的并不是HTTP。
如果使用net/http不可能实现,那么还有其他方法可以实现吗?
可以使用原始网络编程,即使用net包。
这是错误的。抱歉。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论