summary refs log tree commit diff
path: root/destination.go
diff options
context:
space:
mode:
authorMelonai <einebeere@gmail.com>2021-09-10 23:40:49 +0200
committerMelonai <einebeere@gmail.com>2021-09-10 23:43:57 +0200
commita32b9fe723c633cf5349bb0479d97e1f6d04445d (patch)
treef45869da615f5efcd0b2dd8d1baade6831dd3f4f /destination.go
parent175da8f22cd791e81338fe61e6099125868cf5a0 (diff)
downloadportgate-a32b9fe723c633cf5349bb0479d97e1f6d04445d.tar.zst
portgate-a32b9fe723c633cf5349bb0479d97e1f6d04445d.zip
Refactor path into destination
Diffstat (limited to 'destination.go')
-rw-r--r--destination.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/destination.go b/destination.go
new file mode 100644
index 0000000..d911e3e
--- /dev/null
+++ b/destination.go
@@ -0,0 +1,75 @@
+package portgate
+
+import (
+	"net/url"
+	"path"
+	"strconv"
+	"strings"
+)
+
+// Destination represents a routing destination the user gave.
+type Destination struct {
+	// Identifier to which port of the destination host the path points to and to which the
+	// user's request will be proxied to.
+	Port int
+	// The path without the port identifier.
+	// This is the path which will be requested from the destination.
+	Path string
+	IsPortgatePath bool
+}
+
+// ParseDestinationFromURL creates a Path from the requested URL.
+func DestinationFromURL(p string) Destination {
+	p = path.Clean("/" + p)
+
+	// Get first path part, which is the potential port identifier.
+	destinationIdentifierEnd := strings.Index(p[1:], "/") + 1
+
+	// If there is no '/' in the path, apart from the root, the first part is the entire path
+	if destinationIdentifierEnd == 0 {
+		destinationIdentifierEnd = len(p)
+	}
+
+	destinationIdentifier := p[1:destinationIdentifierEnd]
+
+	// We have to to check that destinationIdentifier is a port
+	port, err := strconv.Atoi(destinationIdentifier)
+	if err == nil {
+		// We got an identifier and can split the path
+		resourcePath := path.Clean("/" + p[destinationIdentifierEnd:])
+
+		return Destination{
+			Port: port,
+			Path: resourcePath,
+		}
+	} else {
+		destination := Destination{
+			Port: 0,
+			Path: p,
+		}
+
+		if strings.HasPrefix(destination.Path, "/_portgate") {
+			destination.IsPortgatePath = true
+			return destination
+		}
+
+		return destination
+	}
+}
+
+// DestinationFromReferer tries to create a Path from the Referer header of the request.
+func (d Destination) AddReferer(referer string) Destination {
+	u, err := url.Parse(referer)
+	if err != nil {
+		return Destination{}
+	}
+
+	// d has the correct resource path but the wrong port, so we create a new destination
+	// with the correct data from both.
+	newDestination := DestinationFromURL(u.Path)
+
+	return Destination{
+		Port: newDestination.Port,
+		Path: d.Path,
+	}
+}
\ No newline at end of file