Skip to content

Commit 1d8f822

Browse files
committed
url: new package
This is just moving the URL code from package http into its own package, which has been planned for a while. Besides clarity, this also breaks a nascent dependency cycle the new template package was about to introduce. Add a gofix module, url, and use it to generate changes outside http and url. Sadness about the churn, gladness about some of the naming improvements. R=dsymonds, bradfitz, rsc, gustavo, r CC=golang-dev https://golang.org/cl/4893043
1 parent d72c96d commit 1d8f822

28 files changed

+566
-265
lines changed

misc/dashboard/builder/http.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"log"
1313
"os"
1414
"strconv"
15+
"url"
1516
)
1617

1718
type param map[string]string
@@ -26,7 +27,7 @@ func dash(meth, cmd string, resp interface{}, args param) os.Error {
2627
log.Println("dash", cmd, args)
2728
}
2829
cmd = "http://" + *dashboard + "/" + cmd
29-
vals := make(http.Values)
30+
vals := make(url.Values)
3031
for k, v := range args {
3132
vals.Add(k, v)
3233
}

src/cmd/godoc/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"runtime"
4545
"strings"
4646
"time"
47+
"url"
4748
)
4849

4950
const defaultAddr = ":6060" // default webserver address
@@ -160,7 +161,7 @@ func loggingHandler(h http.Handler) http.Handler {
160161
}
161162

162163
func remoteSearch(query string) (res *http.Response, err os.Error) {
163-
search := "/search?f=text&q=" + http.URLEscape(query)
164+
search := "/search?f=text&q=" + url.QueryEscape(query)
164165

165166
// list of addresses to try
166167
var addrs []string

src/cmd/gofix/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ GOFILES=\
2323
sortslice.go\
2424
stringssplit.go\
2525
typecheck.go\
26+
url.go\
2627

2728
include ../../Make.cmd
2829

src/cmd/gofix/url.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2011 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
"os"
10+
"go/ast"
11+
)
12+
13+
var _ fmt.Stringer
14+
var _ os.Error
15+
16+
var urlFix = fix{
17+
"url",
18+
url,
19+
`Move the URL pieces of package http into a new package, url.
20+
21+
http://codereview.appspot.com/4893043
22+
`,
23+
}
24+
25+
func init() {
26+
register(urlFix)
27+
}
28+
29+
var urlRenames = []struct{ in, out string }{
30+
{"ParseURL", "Parse"},
31+
{"ParseURLReference", "ParseWithReference"},
32+
{"ParseQuery", "ParseQuery"},
33+
{"Values", "Values"},
34+
{"URLEscape", "QueryEscape"},
35+
{"URLUnescape", "QueryUnescape"},
36+
{"URLError", "Error"},
37+
{"URLEscapeError", "EscapeError"},
38+
}
39+
40+
func url(f *ast.File) bool {
41+
if imports(f, "url") || !imports(f, "http") {
42+
return false
43+
}
44+
45+
fixed := false
46+
47+
// Update URL code.
48+
urlWalk := func(n interface{}) {
49+
// Is it an identifier?
50+
if ident, ok := n.(*ast.Ident); ok && ident.Name == "url" {
51+
ident.Name = "url_"
52+
return
53+
}
54+
// Find declared identifiers called url that might be confused.
55+
// TODO: Why does gofix not walk the Names in a ValueSpec?
56+
// TODO: Just a bug; fix later as it will have consequences.
57+
if valSpec, ok := n.(*ast.ValueSpec); ok {
58+
for _, ident := range valSpec.Names {
59+
if ident.Name == "url" {
60+
ident.Name = "url_"
61+
}
62+
}
63+
}
64+
// Parameter and result names.
65+
if fn, ok := n.(*ast.FuncType); ok {
66+
fixed = urlDoFields(fn.Params) || fixed
67+
fixed = urlDoFields(fn.Results) || fixed
68+
}
69+
}
70+
71+
// Fix up URL code and add import, at most once.
72+
fix := func() {
73+
if fixed {
74+
return
75+
}
76+
walk(f, urlWalk)
77+
addImport(f, "url")
78+
fixed = true
79+
}
80+
81+
walk(f, func(n interface{}) {
82+
// Rename functions and methods.
83+
if expr, ok := n.(ast.Expr); ok {
84+
for _, s := range urlRenames {
85+
if isPkgDot(expr, "http", s.in) {
86+
fix()
87+
expr.(*ast.SelectorExpr).X.(*ast.Ident).Name = "url"
88+
expr.(*ast.SelectorExpr).Sel.Name = s.out
89+
return
90+
}
91+
}
92+
}
93+
})
94+
95+
// Remove the http import if no longer needed.
96+
if fixed && !usesImport(f, "http") {
97+
deleteImport(f, "http")
98+
}
99+
100+
return fixed
101+
}
102+
103+
func urlDoFields(list *ast.FieldList) (fixed bool) {
104+
if list == nil {
105+
return
106+
}
107+
for _, field := range list.List {
108+
for _, ident := range field.Names {
109+
if ident.Name == "url" {
110+
fixed = true
111+
ident.Name = "url_"
112+
}
113+
}
114+
}
115+
return
116+
}

src/cmd/gofix/url_test.go

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2011 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
func init() {
8+
addTestCases(urlTests)
9+
}
10+
11+
var urlTests = []testCase{
12+
{
13+
Name: "url.0",
14+
In: `package main
15+
16+
import (
17+
"http"
18+
)
19+
20+
func f() {
21+
http.ParseURL(a)
22+
http.ParseURLReference(a)
23+
http.ParseQuery(a)
24+
m := http.Values{a: b}
25+
http.URLEscape(a)
26+
http.URLUnescape(a)
27+
var x http.URLError
28+
var y http.URLEscapeError
29+
}
30+
`,
31+
Out: `package main
32+
33+
import "url"
34+
35+
func f() {
36+
url.Parse(a)
37+
url.ParseWithReference(a)
38+
url.ParseQuery(a)
39+
m := url.Values{a: b}
40+
url.QueryEscape(a)
41+
url.QueryUnescape(a)
42+
var x url.Error
43+
var y url.EscapeError
44+
}
45+
`,
46+
},
47+
{
48+
Name: "url.1",
49+
In: `package main
50+
51+
import (
52+
"http"
53+
)
54+
55+
func f() {
56+
http.ParseURL(a)
57+
var x http.Request
58+
}
59+
`,
60+
Out: `package main
61+
62+
import (
63+
"http"
64+
"url"
65+
)
66+
67+
func f() {
68+
url.Parse(a)
69+
var x http.Request
70+
}
71+
`,
72+
},
73+
{
74+
Name: "url.2",
75+
In: `package main
76+
77+
import (
78+
"http"
79+
)
80+
81+
func f() {
82+
http.ParseURL(a)
83+
var url = 23
84+
url, x := 45, y
85+
}
86+
87+
func g(url string) string {
88+
return url
89+
}
90+
91+
func h() (url string) {
92+
return url
93+
}
94+
`,
95+
Out: `package main
96+
97+
import "url"
98+
99+
func f() {
100+
url.Parse(a)
101+
var url_ = 23
102+
url_, x := 45, y
103+
}
104+
105+
func g(url_ string) string {
106+
return url_
107+
}
108+
109+
func h() (url_ string) {
110+
return url_
111+
}
112+
`,
113+
},
114+
{
115+
Name: "url.3",
116+
In: `package main
117+
118+
import "http"
119+
120+
type U struct{ url string }
121+
122+
func f() {
123+
var u U
124+
u.url = "x"
125+
}
126+
127+
func (url *T) m() string {
128+
return url
129+
}
130+
`,
131+
Out: `package main
132+
133+
import "http"
134+
135+
type U struct{ url string }
136+
137+
func f() {
138+
var u U
139+
u.url = "x"
140+
}
141+
142+
func (url *T) m() string {
143+
return url
144+
}
145+
`,
146+
},
147+
}

src/pkg/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ DIRS=\
164164
time\
165165
try\
166166
unicode\
167+
url\
167168
utf16\
168169
utf8\
169170
websocket\

src/pkg/exp/template/funcs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ package template
77
import (
88
"bytes"
99
"fmt"
10-
"http"
1110
"io"
1211
"os"
1312
"reflect"
1413
"strings"
1514
"unicode"
15+
"url"
1616
"utf8"
1717
)
1818

@@ -364,5 +364,5 @@ func URLQueryEscaper(args ...interface{}) string {
364364
if !ok {
365365
s = fmt.Sprint(args...)
366366
}
367-
return http.URLEscape(s)
367+
return url.QueryEscape(s)
368368
}

src/pkg/http/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,5 @@ GOFILES=\
2222
status.go\
2323
transfer.go\
2424
transport.go\
25-
url.go\
2625

2726
include ../../Make.pkg

src/pkg/http/cgi/child.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"os"
1919
"strconv"
2020
"strings"
21+
"url"
2122
)
2223

2324
// Request returns the HTTP request as represented in the current
@@ -93,7 +94,7 @@ func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
9394
// Hostname is provided, so we can reasonably construct a URL,
9495
// even if we have to assume 'http' for the scheme.
9596
r.RawURL = "http://" + r.Host + params["REQUEST_URI"]
96-
url, err := http.ParseURL(r.RawURL)
97+
url, err := url.Parse(r.RawURL)
9798
if err != nil {
9899
return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL)
99100
}
@@ -103,7 +104,7 @@ func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
103104
// failed to parse
104105
if r.URL == nil {
105106
r.RawURL = params["REQUEST_URI"]
106-
url, err := http.ParseURL(r.RawURL)
107+
url, err := url.Parse(r.RawURL)
107108
if err != nil {
108109
return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL)
109110
}

src/pkg/http/cgi/host.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ func (h *Handler) printf(format string, v ...interface{}) {
276276
}
277277

278278
func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Request, path string) {
279-
url, err := req.URL.ParseURL(path)
279+
url, err := req.URL.Parse(path)
280280
if err != nil {
281281
rw.WriteHeader(http.StatusInternalServerError)
282282
h.printf("cgi: error resolving local URI path %q: %v", path, err)

0 commit comments

Comments
 (0)