Skip to content

Commit 303eed0

Browse files
authored
add userinfo (username/password) (#25)
* add userinfo (username/password) * add go 1.18 and 1.19 tests * update authority to include userinfo instead of scheme
1 parent 8d2de68 commit 303eed0

File tree

8 files changed

+85
-15
lines changed

8 files changed

+85
-15
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ jobs:
44
test:
55
strategy:
66
matrix:
7-
go-version: [1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x]
7+
go-version: [1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x, 1.19.x]
88
os: [ubuntu-latest]
99
runs-on: ${{ matrix.os }}
1010
steps:

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,21 @@ Known Issues:
1212

1313
# uri
1414

15-
A convenient and easy way to convert from a uri to a struct or vic-versa.
15+
A convenient and easy way to convert from a uri to a struct or vic-versa. [wikipedia](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier)
1616

17-
## keywords
17+
![](./assets/URI_syntax_diagram.svg.png)
1818

19+
## special keywords
20+
21+
- origin (scheme:host/path)
1922
- scheme
20-
- host
21-
- path
22-
- authority (schema:host)
23-
- origin (schema:host/path)
23+
- authority (userinfo@host)
24+
- userinfo
25+
- username
26+
- password
27+
- host (includes port)
28+
- port
29+
- fragment
2430

2531
## struct tags
2632

assets/URI_syntax_diagram.svg.png

13.9 KB
Loading

marshal.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,12 @@ const (
2525
scheme = "scheme"
2626
host = "host"
2727
path = "path"
28+
userinfo = "userinfo"
29+
password = "password"
30+
username = "username"
2831
filename = "filename"
29-
authority = "authority" // scheme://host
30-
origin = "origin" // scheme://host/path
32+
authority = "authority" // userinfo@host
33+
origin = "origin" // scheme://host/path - see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
3134
fragment = "fragment" // anything after hash #
3235
)
3336

@@ -101,6 +104,20 @@ func parseStruct(u *url.URL, uVal *url.Values, vStruct reflect.Value) {
101104
case fragment:
102105
u.Fragment = fs
103106
continue
107+
case userinfo:
108+
u.User = url.User(fs)
109+
continue
110+
case username:
111+
p, set := u.User.Password()
112+
if set {
113+
u.User = url.UserPassword(fs, p)
114+
} else {
115+
u.User = url.User(fs)
116+
}
117+
continue
118+
case password:
119+
u.User = url.UserPassword(u.User.Username(), fs)
120+
continue
104121
case origin: // scheme://host/path
105122
l, err := url.Parse(fs)
106123
if err == nil {
@@ -109,11 +126,11 @@ func parseStruct(u *url.URL, uVal *url.Values, vStruct reflect.Value) {
109126
u.Path = l.Path
110127
}
111128
continue
112-
case authority: // scheme://host
129+
case authority: //userinfo@host
113130
l, err := url.Parse(fs)
114131
if err == nil {
132+
u.User = l.User
115133
u.Host = l.Host
116-
u.Scheme = l.Scheme
117134
}
118135
continue
119136
case "-": // skip disabled fields

marshal_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,27 @@ func TestMarshal(t *testing.T) {
211211
Input: struct {
212212
Authority string `uri:"authority"`
213213
}{
214-
Authority: "http://localhost:8080/path/to/file.txt",
214+
Authority: "http://user:pass@localhost:8080/path/to/file.txt",
215215
},
216-
Expected: "http://localhost:8080",
216+
Expected: "//user:pass@localhost:8080",
217+
},
218+
"username_password": {
219+
Input: struct {
220+
Password string `uri:"password"`
221+
Username string `uri:"username"`
222+
}{
223+
Username: "user",
224+
Password: "pass",
225+
},
226+
Expected: "//user:pass@",
227+
},
228+
"userinfo": {
229+
Input: struct {
230+
UserInfo string `uri:"userinfo"`
231+
}{
232+
UserInfo: "userinfo:asd",
233+
},
234+
Expected: "//userinfo:asd@",
217235
},
218236
/* how should this case be handled?
219237
"origin override": {

unmarshal.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ func Unmarshal(uri string, v interface{}) error {
8080
data = u.Host
8181
case path:
8282
data = u.Path
83+
case userinfo:
84+
data = u.User.String()
85+
case username:
86+
data = u.User.Username()
87+
case password:
88+
data, _ = u.User.Password()
8389
case filename:
8490
_, data = filepath.Split(u.Path)
8591
case origin:
@@ -88,7 +94,10 @@ func Unmarshal(uri string, v interface{}) error {
8894
data = u.Path
8995
}
9096
case authority:
91-
data = fmt.Sprintf("%s://%s", u.Scheme, u.Host)
97+
data = u.Host
98+
if userinfo := u.User.String(); userinfo != "" {
99+
data = fmt.Sprintf("%s@%s", userinfo, u.Host)
100+
}
92101
case fragment:
93102
data = u.Fragment
94103
default:

unmarshal_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,20 +375,40 @@ func TestTags(t *testing.T) {
375375
uri: "https://localhost:8080/usr/bin",
376376
expected: &struct {
377377
Authority string `uri:"authority"`
378-
}{Authority: "https://localhost:8080"},
378+
}{Authority: "localhost:8080"},
379+
},
380+
"Authority with userinfo": {
381+
uri: "https://user:pass@localhost:8080/usr/bin",
382+
expected: &struct {
383+
Authority string `uri:"authority"`
384+
}{Authority: "user:pass@localhost:8080"},
379385
},
380386
"Origin uri tag": {
381387
uri: "https://localhost:8080/usr/bin",
382388
expected: &struct {
383389
Origin string `uri:"Origin"`
384390
}{Origin: "https://localhost:8080/usr/bin"},
385391
},
392+
"Origin with userinfo": {
393+
uri: "https://user:pass@localhost:8080/usr/bin",
394+
expected: &struct {
395+
Origin string `uri:"Origin"`
396+
}{Origin: "https://localhost:8080/usr/bin"},
397+
},
386398
"Origin uri tag without authority": {
387399
uri: "/usr/bin",
388400
expected: &struct {
389401
Origin string `uri:"Origin"`
390402
}{Origin: "/usr/bin"},
391403
},
404+
"userinfo": {
405+
uri: "//user:pass@localhost:8080/usr/bin",
406+
expected: &struct {
407+
Username string `uri:"username"`
408+
Password string `uri:"password"`
409+
UserInfo string `uri:"userinfo"`
410+
}{Username: "user", Password: "pass", UserInfo: "user:pass"},
411+
},
392412
"Custom int name": {
393413
uri: "?NewInt=10",
394414
expected: &struct {

uri.drawio.png

57.9 KB
Loading

0 commit comments

Comments
 (0)