mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
net.http: more robust handling of relative /path URL redirects
This commit is contained in:
parent
67e7ad13de
commit
0ad5d53423
@ -50,6 +50,7 @@ fn (dtp DTP) read() []byte {
|
|||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
data << buf[i]
|
data << buf[i]
|
||||||
}
|
}
|
||||||
|
unsafe { free(buf) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
@ -193,7 +193,7 @@ pub fn parse_headers(lines []string) map[string]string {
|
|||||||
|
|
||||||
// do will send the HTTP request and returns `http.Response` as soon as the response is recevied
|
// do will send the HTTP request and returns `http.Response` as soon as the response is recevied
|
||||||
pub fn (req &Request) do() ?Response {
|
pub fn (req &Request) do() ?Response {
|
||||||
url := urllib.parse(req.url) or {
|
mut url := urllib.parse(req.url) or {
|
||||||
return error('http.Request.do: invalid url ${req.url}')
|
return error('http.Request.do: invalid url ${req.url}')
|
||||||
}
|
}
|
||||||
mut rurl := url
|
mut rurl := url
|
||||||
@ -211,7 +211,13 @@ pub fn (req &Request) do() ?Response {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
// follow any redirects
|
// follow any redirects
|
||||||
redirect_url := resp.headers['Location']
|
mut redirect_url := resp.headers['Location']
|
||||||
|
if redirect_url.len > 0 && redirect_url[0] == `/` {
|
||||||
|
url.set_path(redirect_url) or {
|
||||||
|
return error('http.request.do: invalid path in redirect: "$redirect_url"')
|
||||||
|
}
|
||||||
|
redirect_url = url.str()
|
||||||
|
}
|
||||||
qrurl := urllib.parse(redirect_url) or {
|
qrurl := urllib.parse(redirect_url) or {
|
||||||
return error('http.request.do: invalid URL in redirect "$redirect_url"')
|
return error('http.request.do: invalid URL in redirect "$redirect_url"')
|
||||||
}
|
}
|
||||||
|
@ -36,3 +36,12 @@ fn test_public_servers() {
|
|||||||
assert res.text.len > 0
|
assert res.text.len > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_relative_redirects() {
|
||||||
|
$if !network ? { return }
|
||||||
|
res := http.get('https://httpbin.org/relative-redirect/3?abc=xyz') or { panic(err) }
|
||||||
|
assert 200 == res.status_code
|
||||||
|
assert res.text.len > 0
|
||||||
|
assert res.text.contains('"abc": "xyz"')
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -255,9 +255,10 @@ pub fn (s Socket) send_string(sdata string) ?int {
|
|||||||
return s.send(sdata.str, sdata.len)
|
return s.send(sdata.str, sdata.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive string data from socket
|
// receive string data from socket. NB: you are responsible for freeing the returned byteptr
|
||||||
pub fn (s Socket) recv(bufsize int) (byteptr,int) {
|
pub fn (s Socket) recv(bufsize int) (byteptr,int) {
|
||||||
buf := malloc(bufsize)
|
mut buf := byteptr(0)
|
||||||
|
unsafe { buf = malloc(bufsize) }
|
||||||
res := C.recv(s.sockfd, buf, bufsize, 0)
|
res := C.recv(s.sockfd, buf, bufsize, 0)
|
||||||
return buf,res
|
return buf,res
|
||||||
}
|
}
|
||||||
|
@ -326,6 +326,7 @@ pub mut:
|
|||||||
raw_query string // encoded query values, without '?'
|
raw_query string // encoded query values, without '?'
|
||||||
fragment string // fragment for references, without '#'
|
fragment string // fragment for references, without '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
// user returns a Userinfo containing the provided username
|
// user returns a Userinfo containing the provided username
|
||||||
// and no password set.
|
// and no password set.
|
||||||
pub fn user(username string) &Userinfo {
|
pub fn user(username string) &Userinfo {
|
||||||
@ -650,7 +651,7 @@ fn parse_host(host string) ?string {
|
|||||||
// - set_path('/foo%2fbar') will set path='/foo/bar' and raw_path='/foo%2fbar'
|
// - set_path('/foo%2fbar') will set path='/foo/bar' and raw_path='/foo%2fbar'
|
||||||
// set_path will return an error only if the provided path contains an invalid
|
// set_path will return an error only if the provided path contains an invalid
|
||||||
// escaping.
|
// escaping.
|
||||||
fn (u mut URL) set_path(p string) ?bool {
|
pub fn (u mut URL) set_path(p string) ?bool {
|
||||||
path := unescape(p, .encode_path) or {
|
path := unescape(p, .encode_path) or {
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
@ -755,7 +756,7 @@ fn valid_optional_port(port string) bool {
|
|||||||
// the form host/path does not add its own /.
|
// the form host/path does not add its own /.
|
||||||
// - if u.raw_query is empty, ?query is omitted.
|
// - if u.raw_query is empty, ?query is omitted.
|
||||||
// - if u.fragment is empty, #fragment is omitted.
|
// - if u.fragment is empty, #fragment is omitted.
|
||||||
pub fn (u &URL) str() string {
|
pub fn (u URL) str() string {
|
||||||
mut buf := strings.new_builder(200)
|
mut buf := strings.new_builder(200)
|
||||||
if u.scheme != '' {
|
if u.scheme != '' {
|
||||||
buf.write(u.scheme)
|
buf.write(u.scheme)
|
||||||
@ -765,7 +766,7 @@ pub fn (u &URL) str() string {
|
|||||||
buf.write(u.opaque)
|
buf.write(u.opaque)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if u.scheme != '' || u.host != '' || !u.user.empty() {
|
if u.scheme != '' || u.host != '' || (u.user != 0 && !u.user.empty()) {
|
||||||
if u.host != '' || u.path != '' || !u.user.empty() {
|
if u.host != '' || u.path != '' || !u.user.empty() {
|
||||||
buf.write('//')
|
buf.write('//')
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user