github.com/google/go-safeweb@v0.0.0-20231219055052-64d8cfc90fbb/safehttp/url.go (about)

     1  // Copyright 2020 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //	https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package safehttp
    16  
    17  import (
    18  	"net/url"
    19  )
    20  
    21  // URL represents a parsed URL (technically, a URI reference).
    22  type URL struct {
    23  	url *url.URL
    24  }
    25  
    26  // Query parses the query string in the URL and returns a form
    27  // containing its values. The returned error describes the first
    28  // decoding error encountered, if any.
    29  func (u URL) Query() (Form, error) {
    30  	v, err := url.ParseQuery(u.url.RawQuery)
    31  	if err != nil {
    32  		return Form{}, err
    33  	}
    34  	return Form{values: map[string][]string(v)}, nil
    35  }
    36  
    37  // String reassembles the URL into a valid URL string.
    38  //
    39  // The method uses the net/url.EscapedPath method to obtain the path.
    40  // See the net/url.EscapedPath method for more details.
    41  func (u URL) String() string {
    42  	// The escaping is perfomed by u.url.String()
    43  	return u.url.String()
    44  }
    45  
    46  // Host returns the host or the host:port of the URL.
    47  func (u URL) Host() string {
    48  	return u.url.Host
    49  }
    50  
    51  // Hostname returns the host of the URL, stripping any valid
    52  // port number if present.
    53  //
    54  // If the result is enclosed in square brackets, as literal IPv6
    55  // addresses are, the square brackets are removed from the result.
    56  func (u URL) Hostname() string {
    57  	return u.url.Hostname()
    58  }
    59  
    60  // Port returns the port part of the URL. If the
    61  // host doesn't contain a valid port number, Port returns an
    62  // empty string.
    63  func (u URL) Port() string {
    64  	return u.url.Port()
    65  }
    66  
    67  // Path returns the path of the URL.
    68  //
    69  // Note that the path is stored in decoded form: /%47%6f%2f
    70  // becomes /Go/. A consequence is that it is impossible to tell
    71  // which slashes in the path were slashes in the rawURL and which
    72  // were %2f.
    73  func (u URL) Path() string {
    74  	return u.url.Path
    75  }
    76  
    77  // ParseURL parses a raw URL string into a URL structure.
    78  //
    79  // The raw URl may be relative (a path, without a host) or absolute (starting
    80  // with a scheme). Trying to parse a hostname and path without a scheme is
    81  // invalid but may not necessarily return an error, due to parsing ambiguities.
    82  func ParseURL(rawurl string) (*URL, error) {
    83  	parsed, err := url.Parse(rawurl)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return &URL{url: parsed}, nil
    88  }