mirror of
https://github.com/laravel-ls/uri
synced 2026-07-04 00:23:39 +02:00
uri: fix URI json tag and add {,Un}MarshalJSON methods
This commit is contained in:
parent
a62f200b52
commit
90a5178f88
1 changed files with 215 additions and 16 deletions
229
uri.go
229
uri.go
|
|
@ -5,13 +5,25 @@
|
||||||
package uri
|
package uri
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
// FileScheme schema of filesystem path.
|
// FileScheme schema of filesystem path.
|
||||||
const FileScheme = "file"
|
FileScheme = "file"
|
||||||
|
|
||||||
|
// HTTPScheme schema of http.
|
||||||
|
HTTPScheme = "http"
|
||||||
|
|
||||||
|
// HTTPSScheme schema of https.
|
||||||
|
HTTPSScheme = "https"
|
||||||
|
)
|
||||||
|
|
||||||
// URI Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
|
// URI Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
|
||||||
//
|
//
|
||||||
|
|
@ -29,10 +41,10 @@ const FileScheme = "file"
|
||||||
type URI struct {
|
type URI struct {
|
||||||
// Authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'.
|
// Authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||||
// The part between the first double slashes and the next slash.
|
// The part between the first double slashes and the next slash.
|
||||||
Authority string `json:"authority,omitempty"`
|
Authority string `json:"authority"`
|
||||||
|
|
||||||
// Fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'.
|
// Fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||||
Fragment string `json:"fragment,omitempty"`
|
Fragment string `json:"fragment"`
|
||||||
|
|
||||||
// FsPath returns a string representing the corresponding file system path of this URI.
|
// FsPath returns a string representing the corresponding file system path of this URI.
|
||||||
//
|
//
|
||||||
|
|
@ -56,18 +68,212 @@ type URI struct {
|
||||||
// namely the server name, would be missing.
|
// namely the server name, would be missing.
|
||||||
//
|
//
|
||||||
// Therefore `URI#fsPath` exists - it's sugar to ease working with URIs that represent files on disk (`file` scheme).
|
// Therefore `URI#fsPath` exists - it's sugar to ease working with URIs that represent files on disk (`file` scheme).
|
||||||
FsPath string `json:"fsPath,omitempty"`
|
FsPath string `json:"fsPath"`
|
||||||
|
|
||||||
// Path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'.
|
// Path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path"`
|
||||||
|
|
||||||
// Query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'.
|
// Query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||||
Query string `json:"query,omitempty"`
|
Query string `json:"query"`
|
||||||
|
|
||||||
// Scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
|
// Scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||||
//
|
//
|
||||||
// The part before the first colon.
|
// The part before the first colon.
|
||||||
Scheme string `json:"scheme,omitempty"`
|
Scheme string `json:"scheme"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler.
|
||||||
|
func (u *URI) MarshalJSON() ([]byte, error) {
|
||||||
|
buf := bytes.NewBuffer(make([]byte, 0))
|
||||||
|
buf.WriteString("{")
|
||||||
|
|
||||||
|
comma := false
|
||||||
|
// "Authority" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "authority" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"authority\": ")
|
||||||
|
if tmp, err := json.Marshal(u.Authority); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
// "Fragment" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "fragment" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"fragment\": ")
|
||||||
|
if tmp, err := json.Marshal(u.Fragment); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
// "FsPath" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "fsPath" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"fsPath\": ")
|
||||||
|
if tmp, err := json.Marshal(u.FsPath); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
// "Path" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "path" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"path\": ")
|
||||||
|
if tmp, err := json.Marshal(u.Path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
// "Query" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "query" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"query\": ")
|
||||||
|
if tmp, err := json.Marshal(u.Query); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
// "Scheme" field is required
|
||||||
|
// only required object types supported for marshal checking (for now)
|
||||||
|
// Marshal the "scheme" field
|
||||||
|
if comma {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("\"scheme\": ")
|
||||||
|
if tmp, err := json.Marshal(u.Scheme); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
buf.Write(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
comma = true
|
||||||
|
|
||||||
|
buf.WriteString("}")
|
||||||
|
rv := buf.Bytes()
|
||||||
|
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
|
func (u *URI) UnmarshalJSON(b []byte) error {
|
||||||
|
var authorityReceived bool
|
||||||
|
var fragmentReceived bool
|
||||||
|
var fsPathReceived bool
|
||||||
|
var pathReceived bool
|
||||||
|
var queryReceived bool
|
||||||
|
var schemeReceived bool
|
||||||
|
var jm map[string]json.RawMessage
|
||||||
|
|
||||||
|
if err := json.Unmarshal(b, &jm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse all the defined properties
|
||||||
|
for k, v := range jm {
|
||||||
|
switch k {
|
||||||
|
case "authority":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.Authority); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
authorityReceived = true
|
||||||
|
|
||||||
|
case "fragment":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.Fragment); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fragmentReceived = true
|
||||||
|
|
||||||
|
case "fsPath":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.FsPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fsPathReceived = true
|
||||||
|
|
||||||
|
case "path":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.Path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pathReceived = true
|
||||||
|
|
||||||
|
case "query":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.Query); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
queryReceived = true
|
||||||
|
|
||||||
|
case "scheme":
|
||||||
|
if err := json.Unmarshal([]byte(v), &u.Scheme); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
schemeReceived = true
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("additional property not allowed: \"" + k + "\"")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if authority (a required property) was received
|
||||||
|
if !authorityReceived {
|
||||||
|
return xerrors.New("\"authority\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if fragment (a required property) was received
|
||||||
|
if !fragmentReceived {
|
||||||
|
return xerrors.New("\"fragment\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if fsPath (a required property) was received
|
||||||
|
if !fsPathReceived {
|
||||||
|
return xerrors.New("\"fsPath\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if path (a required property) was received
|
||||||
|
if !pathReceived {
|
||||||
|
return xerrors.New("\"path\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if query (a required property) was received
|
||||||
|
if !queryReceived {
|
||||||
|
return xerrors.New("\"query\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if scheme (a required property) was received
|
||||||
|
if !schemeReceived {
|
||||||
|
return xerrors.New("\"scheme\" is required but was not present")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements fmt.Stringer.
|
// String implements fmt.Stringer.
|
||||||
|
|
@ -80,7 +286,7 @@ func (u *URI) String() string {
|
||||||
}
|
}
|
||||||
return uri.String()
|
return uri.String()
|
||||||
|
|
||||||
case "http", "https":
|
case HTTPScheme, HTTPSScheme:
|
||||||
uri := &url.URL{
|
uri := &url.URL{
|
||||||
Scheme: u.Scheme,
|
Scheme: u.Scheme,
|
||||||
Host: u.Authority,
|
Host: u.Authority,
|
||||||
|
|
@ -95,13 +301,6 @@ func (u *URI) String() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// State represents a URI State.
|
|
||||||
type State struct {
|
|
||||||
*URI
|
|
||||||
Mid float64 `json:"$mid,omitempty"`
|
|
||||||
External string `json:"external,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse parses and creates a new URI from uri.
|
// Parse parses and creates a new URI from uri.
|
||||||
func Parse(s string) *URI {
|
func Parse(s string) *URI {
|
||||||
u, err := url.Parse(s)
|
u, err := url.Parse(s)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue