Skip to content

Commit

Permalink
Microbox names and namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
danhunsaker committed Jun 18, 2023
1 parent c2acc69 commit bceec63
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 498 deletions.
361 changes: 21 additions & 340 deletions LICENSE

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![Build Status](https://travis-ci.org/nanobox-io/nanobox-router.svg)](https://travis-ci.org/nanobox-io/nanobox-router)
[![GoDoc](https://godoc.org/github.com/nanobox-io/nanobox-router?status.svg)](https://godoc.org/github.com/nanobox-io/nanobox-router)
[![Build Status](https://github.com/mu-box/microbox-router/actions/workflows/ci.yaml/badge.svg)](https://github.com/mu-box/microbox-router/actions)
[![GoDoc](https://godoc.org/github.com/mu-box/microbox-router?status.svg)](https://godoc.org/github.com/mu-box/microbox-router)

# nanobox-router
# microbox-router
Simple client for creating and updating custom defined http[s] and ws[s] proxies/ssl-termination without restarting a server application.

## Status
Expand All @@ -18,7 +18,7 @@ import (
"time"
"os"

"github.com/nanobox-io/nanobox-router"
"github.com/mu-box/microbox-router"
)

func main() {
Expand All @@ -43,7 +43,7 @@ Test it
$ curl -H 'Host: test.com' 127.0.0.1:8888
World, Hello!
```
Congratulations proxymaster! Be sure to check out the [godocs](https://godoc.org/github.com/nanobox-io/nanobox-router) to enhance your app's functionality.
Congratulations proxymaster! Be sure to check out the [godocs](https://godoc.org/github.com/mu-box/microbox-router) to enhance your app's functionality.

## Data types:
#### Route:
Expand Down Expand Up @@ -93,14 +93,14 @@ KeyPair{

## Contributing

Contributions to the nanobox-router project are welcome and encouraged. Contributions should follow the [Nanobox Contribution Process & Guidelines](https://docs.nanobox.io/contributing/).
Contributions to the microbox-router project are welcome and encouraged. Contributions should follow the [Microbox Contribution Process & Guidelines](https://docs.microbox.cloud/contributing/).

## Todo

- Add configurable `ErrorLog` like `net/http/httputil`s ReverseProxy

## Licence

Mozilla Public License Version 2.0
This project is released under [The MIT License](http://opensource.org/licenses/MIT).

[![open source](http://nano-assets.gopagoda.io/open-src/nanobox-open-src.png)](http://nanobox.io/open-source)
[![open source](http://microbox.rocks/assets/open-src/microbox-open-src.png)](http://microbox.cloud/open-source)
112 changes: 54 additions & 58 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
// Copyright (C) Pagoda Box, Inc - All Rights Reserved
// Unauthorized copying of this file, via any medium is strictly prohibited
// Proprietary and confidential

// Package router is a client for creating/maintaining http(s) proxies.
//
// Certificates
// # Certificates
//
// Certificates are stored as a KeyPair which contains the key and certificate.
// A tls.Certificate is created and stored separately and used for serving https
Expand All @@ -15,18 +11,17 @@
//
// Start secure routing as follows:
//
// StartTLS("0.0.0.0:443")
// StartTLS("0.0.0.0:443")
//
// Set certificates as follows:
//
// UpdateCerts([]KeyPair{KeyPair{Key: "abcd123", Cert: "1234abc"}})
// UpdateCerts([]KeyPair{KeyPair{Key: "abcd123", Cert: "1234abc"}})
//
// Get certificates (key/cert pairs) as follows:
//
// keys := Keys()
// keys := Keys()
//
//
// Routes
// # Routes
//
// Routes have 2 implicit parts: matching criteria and action definitions. The
// matching portion includes subdomain, domain, and path. The matching algorighm
Expand All @@ -46,79 +41,80 @@
//
// Start routing as follows:
//
// StartHTTP("0.0.0.0:80")
// StartHTTP("0.0.0.0:80")
//
// Set routes as follows:
//
// UpdateRoutes([]Route{Route{Domain: "test.com", Page: "Hello World!\n"}})
// UpdateRoutes([]Route{Route{Domain: "test.com", Page: "Hello World!\n"}})
//
// Get registered routes as follows:
//
// routes := Routes()
//
// routes := Routes()
//
// Matching Scenarios
// # Matching Scenarios
//
// Requests will always match the route with the longest path defined.
//
// ROUTES
// SUB DOMAIN PATH PAGE
// "" test.com / "test"
// "" test.com /admin "admin"
// ROUTES
// SUB DOMAIN PATH PAGE
// "" test.com / "test"
// "" test.com /admin "admin"
//
// CURL
// REQUEST RESPONSE
// test.com/admin "admin"
// test.com/admin/me "admin"
// admin.test.com "test"
// test.com/admins "test"
// CURL
// REQUEST RESPONSE
// test.com/admin "admin"
// test.com/admin/me "admin"
// admin.test.com "test"
// test.com/admins "test"
//
// A path can include a "*" at the end to match similar requests.
//
// ROUTES
// SUB DOMAIN PATH PAGE
// "" test.com / "test"
// "" test.com /a* "a is for apple"
// "" test.com /b/ "b things"
// ROUTES
// SUB DOMAIN PATH PAGE
// "" test.com / "test"
// "" test.com /a* "a is for apple"
// "" test.com /b/ "b things"
//
// CURL
// REQUEST RESPONSE
// test.com/a "a is for apple"
// test.com/ant "a is for apple"
// test.com/ant/man "a is for apple"
// test.com/b "test"
// test.com/b/bear "b things"
// CURL
// REQUEST RESPONSE
// test.com/a "a is for apple"
// test.com/ant "a is for apple"
// test.com/ant/man "a is for apple"
// test.com/b "test"
// test.com/b/bear "b things"
//
// A subdomain match takes precedence over a domain/path match.
//
// ROUTES
// SUB DOMAIN PATH PAGE
// admin test.com / "admin"
// "" test.com /bill "Buffalo Bill"
// ROUTES
// SUB DOMAIN PATH PAGE
// admin test.com / "admin"
// "" test.com /bill "Buffalo Bill"
//
// CURL
// REQUEST RESPONSE
// admin.test.com/bill "admin"
// users.test.com/bill "Buffalo Bill"
// CURL
// REQUEST RESPONSE
// admin.test.com/bill "admin"
// users.test.com/bill "Buffalo Bill"
//
// If a Route's matcher has a subdomain only, then all requests with that
// particular subdomain will have the Route's defined action applied.
//
// ROUTES
// SUB DOMAIN PATH PAGE
// admin "" / "admin"
// "" test1.com / "test1"
// ROUTES
// SUB DOMAIN PATH PAGE
// admin "" / "admin"
// "" test1.com / "test1"
//
// CURL
// REQUEST RESPONSE
// admin.test1.com "admin"
// admin.test2.com "admin"
//
// # Logging
//
// CURL
// REQUEST RESPONSE
// admin.test1.com "admin"
// admin.test2.com "admin"
// In order to view logs embedded within microbox-router, you must:
//
// Logging
// import "github.com/jcelliott/lumber"
//
// In order to view logs embedded within nanobox-router, you must:
// import "github.com/jcelliott/lumber"
// and set the level of logging desired (see lumber docs for more info)
// lumber.Level(lumber.LvlInt("INFO"))
//
package router // import "github.com/nanobox-io/nanobox-router"
// lumber.Level(lumber.LvlInt("INFO"))
package router // import "github.com/mu-box/microbox-router"
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/mu-box/microbox-router

go 1.20

require (
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25
golang.org/x/net v0.9.0
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 h1:EFT6MH3igZK/dIVqgGbTqWVvkZ7wJ5iGN03SVtvvdd8=
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25/go.mod h1:sWkGw/wsaHtRsT9zGQ/WyJCotGWG/Anow/9hsAcBWRw=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
38 changes: 17 additions & 21 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Copyright (C) Pagoda Box, Inc - All Rights Reserved
// Unauthorized copying of this file, via any medium is strictly prohibited
// Proprietary and confidential

package router

import (
Expand Down Expand Up @@ -34,12 +30,12 @@ var host string
// respond with a 502 - NoRoutes error.
func (self handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if ErrorHandler != nil {
lumber.Trace("[NANOBOX-ROUTER] Serving ErrorHandler")
lumber.Trace("[MICROBOX-ROUTER] Serving ErrorHandler")
ErrorHandler.ServeHTTP(rw, req)
return
}
if self.https {
lumber.Trace("[NANOBOX-ROUTER] Setting X-Forwarded-Proto")
lumber.Trace("[MICROBOX-ROUTER] Setting X-Forwarded-Proto")
req.Header.Set("X-Forwarded-Proto", "https")
} else {
req.Header.Set("X-Forwarded-Proto", "http")
Expand All @@ -48,11 +44,11 @@ func (self handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
host = string(re.ReplaceAll([]byte(req.Host), nil))

// find match
lumber.Trace("[NANOBOX-ROUTER] URL-----%+q", req.URL)
lumber.Trace("[MICROBOX-ROUTER] URL-----%+q", req.URL)
route := bestMatch(host, req.URL.Path)
// lumber.Trace("[NANOBOX-ROUTER] Request Headers: '%+q'", req.Header)
// lumber.Trace("[MICROBOX-ROUTER] Request Headers: '%+q'", req.Header)
if route != nil {
lumber.Trace("[NANOBOX-ROUTER] Route chosen: '%+q'", route)
lumber.Trace("[MICROBOX-ROUTER] Route chosen: '%+q'", route)

// serve page
if route.Page != "" {
Expand Down Expand Up @@ -84,7 +80,7 @@ func (self handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {

// todo: maybe? or just check target's scheme
if strings.ToLower(req.Header.Get("Upgrade")) == "websocket" {
lumber.Trace("[NANOBOX-ROUTER] Websocket detected...")
lumber.Trace("[MICROBOX-ROUTER] Websocket detected...")
ServeWS(rw, req, thisProxy.reverseProxy)
} else {
thisProxy.reverseProxy.ServeHTTP(rw, req)
Expand All @@ -93,7 +89,7 @@ func (self handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}

// no registered route matches the request (routes too specific)
lumber.Debug("[NANOBOX-ROUTER] Unsure where to route!")
lumber.Debug("[MICROBOX-ROUTER] Unsure where to route!")
NoRoutes{}.ServeHTTP(rw, req)
}

Expand All @@ -103,12 +99,12 @@ func (self handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// in a recursive manor until a match is or isn't found. Path matches are scored
// so the route with the longest matching path is chosen.
func bestMatch(host, path string) (route *Route) {
lumber.Trace("[NANOBOX-ROUTER] Checking Request: '%v'...", host+path)
lumber.Trace("[MICROBOX-ROUTER] Checking Request: '%v'...", host+path)
matchScore := 0

routesMutex.RLock()
for i := range routes {
lumber.Trace("[NANOBOX-ROUTER] Checking Route: '%v'", routes[i].SubDomain+"."+routes[i].Domain+routes[i].Path)
lumber.Trace("[MICROBOX-ROUTER] Checking Route: '%v'", routes[i].SubDomain+"."+routes[i].Domain+routes[i].Path)
if subdomainMatch(host, routes[i]) && domainMatch(host, routes[i]) && pathMatch(path, routes[i]) {
// Assign a temporary score to check against current matchscore for
// proper routing. We add length of all parts to get a more exact match
Expand All @@ -129,12 +125,12 @@ func bestMatch(host, path string) (route *Route) {
}

tempScore := len(routes[i].Path) + len(routes[i].SubDomain) + len(routes[i].Domain) + bonus
lumber.Trace("[NANOBOX-ROUTER] tempScore: '%v'", tempScore)
lumber.Trace("[MICROBOX-ROUTER] tempScore: '%v'", tempScore)

if tempScore > matchScore {
matchScore = tempScore
route = &routes[i]
lumber.Trace("[NANOBOX-ROUTER] Matchscore: '%v'", matchScore)
lumber.Trace("[MICROBOX-ROUTER] Matchscore: '%v'", matchScore)
}
}
}
Expand All @@ -146,7 +142,7 @@ func bestMatch(host, path string) (route *Route) {
if len(hostParts) <= 2 {
return nil
}
lumber.Trace("[NANOBOX-ROUTER] Stripping subdomain: '%v'", hostParts[0])
lumber.Trace("[MICROBOX-ROUTER] Stripping subdomain: '%v'", hostParts[0])
// strip a subdomain and try matching again
return bestMatch(strings.Join(hostParts[1:], "."), path)
}
Expand All @@ -165,11 +161,11 @@ func subdomainMatch(requestHost string, r Route) bool {
hostBits := strings.Split(requestHost, ".")
if len(hostBits) > 2 {
subdomain = strings.Join(hostBits[:len(hostBits)-2], ".")
lumber.Trace("[NANOBOX-ROUTER] Subdomain: '%s'", subdomain)
lumber.Trace("[MICROBOX-ROUTER] Subdomain: '%s'", subdomain)
}

match := strings.HasPrefix(subdomain, r.SubDomain)
lumber.Trace("[NANOBOX-ROUTER] Subdomain match? '%t'", match)
lumber.Trace("[MICROBOX-ROUTER] Subdomain match? '%t'", match)
return match
}

Expand All @@ -183,10 +179,10 @@ func domainMatch(requestHost string, r Route) bool {
hostBits := strings.Split(requestHost, ".")
if len(hostBits) >= 2 {
domain = strings.Join(hostBits[len(hostBits)-2:], ".")
lumber.Trace("[NANOBOX-ROUTER] Domain: '%s'", domain)
lumber.Trace("[MICROBOX-ROUTER] Domain: '%s'", domain)
}
match := domain == r.Domain
lumber.Trace("[NANOBOX-ROUTER] Domain match? '%t'", match)
lumber.Trace("[MICROBOX-ROUTER] Domain match? '%t'", match)
return match
}

Expand All @@ -208,6 +204,6 @@ func pathMatch(requestPath string, r Route) bool {
// check for exact match or exact match + "/"
match = (r.Path == requestPath) || strings.HasPrefix(requestPath, r.Path+"/")
}
lumber.Trace("[NANOBOX-ROUTER] Path match: '%t'", match)
lumber.Trace("[MICROBOX-ROUTER] Path match: '%t'", match)
return match
}
4 changes: 0 additions & 4 deletions health.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Copyright (C) Pagoda Box, Inc - All Rights Reserved
// Unauthorized copying of this file, via any medium is strictly prohibited
// Proprietary and confidential

package router

import (
Expand Down
4 changes: 0 additions & 4 deletions http.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Copyright (C) Pagoda Box, Inc - All Rights Reserved
// Unauthorized copying of this file, via any medium is strictly prohibited
// Proprietary and confidential

package router

import (
Expand Down

0 comments on commit bceec63

Please sign in to comment.