@@ -105,16 +105,23 @@ func Parse(urlstr string) (*URL, error) {
105105 switch {
106106 case ! ok :
107107 return nil , ErrUnknownDatabaseScheme
108- case scheme .Driver == "file" && u . Opaque != "" :
108+ case scheme .Driver == "file" :
109109 // determine scheme for file
110- if typ , err := SchemeType (u .Opaque ); err == nil {
111- return Parse (typ + ":" + buildOpaque (u ))
110+ s := u .opaqueOrPath ()
111+ switch {
112+ case u .Transport != "tcp" , strings .Index (u .OriginalScheme , "+" ) != - 1 :
113+ return nil , ErrInvalidTransportProtocol
114+ case s == "" :
115+ return nil , ErrMissingPath
116+ }
117+ if typ , err := SchemeType (s ); err == nil {
118+ return Parse (typ + "://" + u .buildOpaque ())
112119 }
113120 return nil , ErrUnknownFileExtension
114121 case ! scheme .Opaque && u .Opaque != "" :
115122 // if scheme does not understand opaque URLs, retry parsing after
116123 // building fully qualified URL
117- return Parse (u .OriginalScheme + "://" + buildOpaque (u ))
124+ return Parse (u .OriginalScheme + "://" + u . buildOpaque ())
118125 case scheme .Opaque && u .Opaque == "" :
119126 // force Opaque
120127 u .Opaque , u .Host , u .Path , u .RawPath = u .Host + u .Path , "" , "" , ""
@@ -234,10 +241,35 @@ func (u *URL) Normalize(sep, empty string, cut int) string {
234241 return strings .Join (s , sep )
235242}
236243
244+ // buildOpaque builds a opaque path.
245+ func (u * URL ) buildOpaque () string {
246+ var up string
247+ if u .User != nil {
248+ up = u .User .String () + "@"
249+ }
250+ var q string
251+ if u .RawQuery != "" {
252+ q = "?" + u .RawQuery
253+ }
254+ var f string
255+ if u .Fragment != "" {
256+ f = "#" + u .Fragment
257+ }
258+ return up + u .opaqueOrPath () + q + f
259+ }
260+
261+ // opaqueOrPath returns the opaque or path value.
262+ func (u * URL ) opaqueOrPath () string {
263+ if u .Opaque != "" {
264+ return u .Opaque
265+ }
266+ return u .Path
267+ }
268+
237269// SchemeType returns the scheme type for a path.
238270func SchemeType (name string ) (string , error ) {
239271 // try to resolve the path on unix systems
240- if runtime .GOOS != "windows" /*&& !mode(name).IsRegular()*/ {
272+ if runtime .GOOS != "windows" {
241273 if typ , ok := resolveType (name ); ok {
242274 return typ , nil
243275 }
@@ -315,21 +347,13 @@ var OpenFile = func(name string) (fs.File, error) {
315347 return f , nil
316348}
317349
318- // buildOpaque builds a opaque path from u.
319- func buildOpaque (u * URL ) string {
320- var q string
321- if u .RawQuery != "" {
322- q = "?" + u .RawQuery
323- }
324- var f string
325- if u .Fragment != "" {
326- f = "#" + u .Fragment
327- }
328- return u .Opaque + q + f
329- }
330-
331350// resolveType tries to resolve a path to a Unix domain socket or directory.
332351func resolveType (s string ) (string , bool ) {
352+ if i := strings .LastIndex (s , "?" ); i != - 1 {
353+ if _ , err := Stat (s [:i ]); err == nil {
354+ s = s [:i ]
355+ }
356+ }
333357 dir := s
334358 for dir != "" && dir != "/" && dir != "." {
335359 // chop off :4444 port
0 commit comments