diff --git a/pkg/protocol/uri.go b/pkg/protocol/uri.go index 4fd8788e5..73b5b984c 100644 --- a/pkg/protocol/uri.go +++ b/pkg/protocol/uri.go @@ -49,7 +49,6 @@ import ( "github.com/cloudwego/hertz/internal/bytesconv" "github.com/cloudwego/hertz/internal/bytestr" "github.com/cloudwego/hertz/internal/nocopy" - "github.com/cloudwego/hertz/pkg/common/hlog" ) // AcquireURI returns an empty URI instance from the pool. @@ -388,11 +387,7 @@ func getScheme(rawURL []byte) (scheme, path []byte) { return nil, rawURL } case c == ':': - if i == 0 { - hlog.Errorf("error happened when try to parse the rawURL(%s): missing protocol scheme", rawURL) - return nil, nil - } - return rawURL[:i], rawURL[i+1:] + return checkSchemeWhenCharIsColon(i, rawURL) default: // we have encountered an invalid character, // so there is no valid scheme diff --git a/pkg/protocol/uri_unix.go b/pkg/protocol/uri_unix.go index 0127ceef0..d3726d8aa 100644 --- a/pkg/protocol/uri_unix.go +++ b/pkg/protocol/uri_unix.go @@ -44,6 +44,8 @@ package protocol +import "github.com/cloudwego/hertz/pkg/common/hlog" + func addLeadingSlash(dst, src []byte) []byte { // add leading slash for unix paths if len(src) == 0 || src[0] != '/' { @@ -52,3 +54,13 @@ func addLeadingSlash(dst, src []byte) []byte { return dst } + +// checkSchemeWhenCharIsColon check url begin with : +// Scenarios that handle protocols like "http:" +func checkSchemeWhenCharIsColon(i int, rawURL []byte) (scheme, path []byte) { + if i == 0 { + hlog.Errorf("error happened when try to parse the rawURL(%s): missing protocol scheme", rawURL) + return + } + return rawURL[:i], rawURL[i+1:] +} diff --git a/pkg/protocol/uri_unix_test.go b/pkg/protocol/uri_unix_test.go new file mode 100644 index 000000000..0bd843707 --- /dev/null +++ b/pkg/protocol/uri_unix_test.go @@ -0,0 +1,61 @@ +//go:build !windows +// +build !windows + +/* + * Copyright 2022 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * The MIT License (MIT) + * + * Copyright (c) 2015-present Aliaksandr Valialkin, VertaMedia, Kirill Danshin, Erik Dubbelboer, FastHTTP Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file may have been modified by CloudWeGo authors. All CloudWeGo + * Modifications are Copyright 2022 CloudWeGo Authors. + */ + +package protocol + +import ( + "testing" + + "github.com/cloudwego/hertz/pkg/common/test/assert" +) + +func TestGetScheme(t *testing.T) { + scheme, path := getScheme([]byte("https://foo.com")) + assert.DeepEqual(t, "https", string(scheme)) + assert.DeepEqual(t, "//foo.com", string(path)) + + scheme, path = getScheme([]byte(":")) + assert.DeepEqual(t, "", string(scheme)) + assert.DeepEqual(t, "", string(path)) +} diff --git a/pkg/protocol/uri_windows.go b/pkg/protocol/uri_windows.go index abf13e72f..11d7d86e0 100644 --- a/pkg/protocol/uri_windows.go +++ b/pkg/protocol/uri_windows.go @@ -44,6 +44,8 @@ package protocol +import "github.com/cloudwego/hertz/pkg/common/hlog" + func addLeadingSlash(dst, src []byte) []byte { // zero length and "C:/" case isDisk := len(src) > 2 && src[1] == ':' @@ -53,3 +55,24 @@ func addLeadingSlash(dst, src []byte) []byte { return dst } + +// checkSchemeWhenCharIsColon check url begin with : +// Scenarios that handle protocols like "http:" +// Add the path to the win file, e.g. "E:/gopath", "E:/". +func checkSchemeWhenCharIsColon(i int, rawURL []byte) (scheme, path []byte) { + if i == 0 { + hlog.Errorf("error happened when trying to parse the rawURL(%s): missing protocol scheme", rawURL) + return + } + if i+2 < len(rawURL) && rawURL[i+1] == '/' { + if rawURL[i+2] == '/' { + return rawURL[:i], rawURL[i+1:] + } + return nil, rawURL + } + + if len(rawURL) == i+2 && rawURL[i+1] == '/' { + return nil, rawURL + } + return +} diff --git a/pkg/protocol/uri_windows_test.go b/pkg/protocol/uri_windows_test.go index 507924b97..bfc3a0830 100644 --- a/pkg/protocol/uri_windows_test.go +++ b/pkg/protocol/uri_windows_test.go @@ -14,7 +14,11 @@ package protocol -import "testing" +import ( + "testing" + + "github.com/cloudwego/hertz/pkg/common/test/assert" +) func TestURIPathNormalizeIssue86(t *testing.T) { t.Parallel() @@ -26,3 +30,21 @@ func TestURIPathNormalizeIssue86(t *testing.T) { testURIPathNormalize(t, &u, "/..\\..\\..\\..\\..\\", "/") testURIPathNormalize(t, &u, "/..%5c..%5cfoo", "/foo") } + +func TestGetScheme(t *testing.T) { + scheme, path := getScheme([]byte("E:/file.go")) + assert.DeepEqual(t, "", string(scheme)) + assert.DeepEqual(t, "E:/file.go", string(path)) + + scheme, path = getScheme([]byte("E:/")) + assert.DeepEqual(t, "", string(scheme)) + assert.DeepEqual(t, "E:/", string(path)) + + scheme, path = getScheme([]byte("https://foo.com")) + assert.DeepEqual(t, "https", string(scheme)) + assert.DeepEqual(t, "//foo.com", string(path)) + + scheme, path = getScheme([]byte(":")) + assert.DeepEqual(t, "", string(scheme)) + assert.DeepEqual(t, "", string(path)) +}