mirror of
https://github.com/v2rayA/v2rayA.git
synced 2026-10-26 03:20:01 +08:00
Commit 0baefc45 (2026-05-03) removed the plugin layer under
service/pkg/plugin and the code that started a plugin per node, but
left the HTTP and ShadowsocksR node types producing what that layer
consumed: a socks outbound to 127.0.0.1:<plugin port> plus a plugin
chain nothing reads. Every http/https proxy node and every SSR node
imported since then connected to a closed local port.
HTTP and HTTPS nodes now produce the core's native http outbound with
the credentials and, for https, TLS to the server name; they no longer
ask for a plugin port. The core has no ShadowsocksR outbound, so an SSR
node's configuration returns an "unsupported" error the latency test
and the automatic selection already understand; the node still parses,
displays and exports so nothing is lost from the store.
157 lines
4.0 KiB
Go
157 lines
4.0 KiB
Go
package serverObj
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"strconv"
|
|
|
|
"github.com/v2rayA/v2rayA/kernel/coreObj"
|
|
)
|
|
|
|
func init() {
|
|
FromLinkRegister("http", NewHTTP)
|
|
FromLinkRegister("https", NewHTTP)
|
|
FromLinkRegister("http-proxy", NewHTTP)
|
|
FromLinkRegister("https-proxy", NewHTTP)
|
|
EmptyRegister("http", func() (ServerObj, error) {
|
|
return new(HTTP), nil
|
|
})
|
|
EmptyRegister("https", func() (ServerObj, error) {
|
|
return new(HTTP), nil
|
|
})
|
|
EmptyRegister("http-proxy", func() (ServerObj, error) {
|
|
return new(HTTP), nil
|
|
})
|
|
EmptyRegister("https-proxy", func() (ServerObj, error) {
|
|
return new(HTTP), nil
|
|
})
|
|
}
|
|
|
|
type HTTP struct {
|
|
Name string `json:"name"`
|
|
Server string `json:"server"`
|
|
Port int `json:"port"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
Protocol string `json:"protocol"`
|
|
}
|
|
|
|
func NewHTTP(link string) (ServerObj, error) {
|
|
return ParseHttpURL(link)
|
|
}
|
|
|
|
func ParseHttpURL(u string) (data *HTTP, err error) {
|
|
t, err := url.Parse(u)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: http proxy link is not a valid URL; expected http-proxy://[user:pass@]host:port", ErrInvalidParameter)
|
|
}
|
|
// A proxy link is scheme://[user:pass@]host[:port][#name]. Anything with
|
|
// a path or query is almost always a subscription URL pasted into the
|
|
// wrong box, so name that instead of returning a bare parameter error.
|
|
if (t.Path != "" && t.Path != "/") || t.RawQuery != "" {
|
|
return nil, fmt.Errorf("%w: http proxy link for %q has a path or query; expected http-proxy://[user:pass@]host:port", ErrInvalidParameter, t.Hostname())
|
|
}
|
|
// A default port only makes sense with a host to connect to; an empty
|
|
// hostname used to be rejected by the port conversion.
|
|
if t.Hostname() == "" {
|
|
return nil, fmt.Errorf("%w: http proxy link has no server address; expected http-proxy://[user:pass@]host:port", ErrInvalidParameter)
|
|
}
|
|
// An absent port falls through to the per-scheme default below.
|
|
port := 0
|
|
if p := t.Port(); p != "" {
|
|
if port, err = strconv.Atoi(p); err != nil {
|
|
return nil, fmt.Errorf("%w: http proxy link for %q has an invalid port; expected http-proxy://[user:pass@]host:port", ErrInvalidParameter, t.Hostname())
|
|
}
|
|
}
|
|
data = &HTTP{
|
|
Name: t.Fragment,
|
|
Server: t.Hostname(),
|
|
Port: port,
|
|
}
|
|
if t.User != nil && len(t.User.String()) > 0 {
|
|
data.Username = t.User.Username()
|
|
data.Password, _ = t.User.Password()
|
|
}
|
|
switch t.Scheme {
|
|
case "https-proxy", "https":
|
|
data.Protocol = "https"
|
|
if data.Port == 0 {
|
|
data.Port = 443
|
|
}
|
|
case "http-proxy", "http":
|
|
data.Protocol = "http"
|
|
if data.Port == 0 {
|
|
data.Port = 80
|
|
}
|
|
default:
|
|
data.Protocol = t.Scheme
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
func (h *HTTP) Configuration(info PriorInfo) (c Configuration, err error) {
|
|
server := coreObj.Server{Address: h.Server, Port: h.Port}
|
|
if h.Username != "" {
|
|
server.Users = []coreObj.OutboundUser{{User: h.Username, Pass: h.Password}}
|
|
}
|
|
var streamSettings *coreObj.StreamSettings
|
|
if h.Protocol == "https" {
|
|
streamSettings = &coreObj.StreamSettings{
|
|
Security: "tls",
|
|
TLSSettings: &coreObj.TLSSettings{ServerName: h.Server},
|
|
}
|
|
}
|
|
return Configuration{
|
|
CoreOutbound: coreObj.OutboundObject{
|
|
Tag: info.Tag,
|
|
Protocol: "http",
|
|
Settings: coreObj.Settings{Servers: []coreObj.Server{server}},
|
|
StreamSettings: streamSettings,
|
|
},
|
|
UDPSupport: false,
|
|
}, nil
|
|
}
|
|
|
|
func (h *HTTP) ExportToURL() string {
|
|
var user *url.Userinfo
|
|
if h.Username != "" && h.Password != "" {
|
|
user = url.UserPassword(h.Username, h.Password)
|
|
}
|
|
u := &url.URL{
|
|
Scheme: h.Protocol,
|
|
User: user,
|
|
Host: net.JoinHostPort(h.Server, strconv.Itoa(h.Port)),
|
|
Fragment: h.Name,
|
|
}
|
|
return u.String()
|
|
}
|
|
|
|
func (h *HTTP) NeedPluginPort() bool {
|
|
return false
|
|
}
|
|
|
|
func (h *HTTP) ProtoToShow() string {
|
|
return h.Protocol
|
|
}
|
|
|
|
func (h *HTTP) GetProtocol() string {
|
|
return h.Protocol
|
|
}
|
|
|
|
func (h *HTTP) GetHostname() string {
|
|
return h.Server
|
|
}
|
|
|
|
func (h *HTTP) GetPort() int {
|
|
return h.Port
|
|
}
|
|
|
|
func (h *HTTP) GetName() string {
|
|
return h.Name
|
|
}
|
|
|
|
func (h *HTTP) SetName(name string) {
|
|
h.Name = name
|
|
}
|